This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 #include <config.h>
469 #include <stdlib.h>
470 #include <limits.h>
471 #include <math.h>
472
473 #include "lisp.h"
474 #include "atimer.h"
475 #include "composite.h"
476 #include "keyboard.h"
477 #include "sysstdio.h"
478 #include "systime.h"
479 #include "frame.h"
480 #include "window.h"
481 #include "termchar.h"
482 #include "dispextern.h"
483 #include "character.h"
484 #include "category.h"
485 #include "buffer.h"
486 #include "charset.h"
487 #include "indent.h"
488 #include "commands.h"
489 #include "keymap.h"
490 #include "disptab.h"
491 #include "termhooks.h"
492 #include "termopts.h"
493 #include "intervals.h"
494 #include "coding.h"
495 #include "region-cache.h"
496 #include "font.h"
497 #include "fontset.h"
498 #include "blockinput.h"
499 #include "xwidget.h"
500 #ifdef HAVE_WINDOW_SYSTEM
501 #include TERM_HEADER
502 #endif
503
504 #ifndef FRAME_OUTPUT_DATA
505 #define FRAME_OUTPUT_DATA(f) (NULL)
506 #endif
507
508 #define DISP_INFINITY 10000000
509
510
511 static Lisp_Object list_of_error;
512
513 #ifdef HAVE_WINDOW_SYSTEM
514
515
516
517
518 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
519 (!NILP (Voverflow_newline_into_fringe) \
520 && FRAME_WINDOW_P ((IT)->f) \
521 && ((IT)->bidi_it.paragraph_dir == R2L \
522 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
523 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
524 && (IT)->current_x == (IT)->last_visible_x)
525
526 #else
527 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
528 #endif
529
530
531
532
533
534 #define IT_DISPLAYING_WHITESPACE(it) \
535 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
536 || ((STRINGP (it->string) \
537 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
538 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
539 || (it->s \
540 && (it->s[IT_BYTEPOS (*it)] == ' ' \
541 || it->s[IT_BYTEPOS (*it)] == '\t')) \
542 || (IT_BYTEPOS (*it) < ZV_BYTE \
543 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
544 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
545
546
547
548 #define NOT_AT_EOL '<'
549 #define NOT_AT_BOL '>'
550 #define LINE_BREAKABLE '|'
551
552 static bool
553 it_char_has_category(struct it *it, int cat)
554 {
555 int ch = 0;
556 if (it->what == IT_CHARACTER)
557 ch = it->c;
558 else if (STRINGP (it->string))
559 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
560 else if (it->s)
561 ch = it->s[IT_BYTEPOS (*it)];
562 else if (IT_BYTEPOS (*it) < ZV_BYTE)
563 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
564
565 if (ch == 0)
566 return false;
567 else
568 return CHAR_HAS_CATEGORY (ch, cat);
569 }
570
571
572 static bool
573 char_can_wrap_before (struct it *it)
574 {
575 if (!word_wrap_by_category)
576 return !IT_DISPLAYING_WHITESPACE (it);
577
578
579
580
581 int not_at_bol;
582 if (it->glyph_row && it->glyph_row->reversed_p)
583 not_at_bol = NOT_AT_EOL;
584 else
585 not_at_bol = NOT_AT_BOL;
586
587
588 return (!IT_DISPLAYING_WHITESPACE (it)
589
590 && !it_char_has_category (it, not_at_bol));
591 }
592
593
594 static bool
595 char_can_wrap_after (struct it *it)
596 {
597 if (!word_wrap_by_category)
598 return IT_DISPLAYING_WHITESPACE (it);
599
600
601
602
603 int not_at_eol;
604 if (it->glyph_row && it->glyph_row->reversed_p)
605 not_at_eol = NOT_AT_BOL;
606 else
607 not_at_eol = NOT_AT_EOL;
608
609 return (IT_DISPLAYING_WHITESPACE (it)
610
611 || (it_char_has_category (it, LINE_BREAKABLE)
612 && !it_char_has_category (it, not_at_eol)));
613 }
614
615 #undef IT_DISPLAYING_WHITESPACE
616 #undef NOT_AT_EOL
617 #undef NOT_AT_BOL
618 #undef LINE_BREAKABLE
619
620
621
622
623 static int
624 fill_column_indicator_column (struct it *it, int char_width)
625 {
626 if (display_fill_column_indicator
627 && !it->w->pseudo_window_p
628 && it->continuation_lines_width == 0
629 && CHARACTERP (Vdisplay_fill_column_indicator_character))
630 {
631 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
632 ? BVAR (current_buffer, fill_column)
633 : Vdisplay_fill_column_indicator_column);
634
635
636
637 if (RANGED_FIXNUMP (0, col, INT_MAX))
638 {
639 int icol = XFIXNUM (col);
640 if (!ckd_mul (&icol, icol, char_width)
641 && !ckd_add (&icol, icol, it->lnum_pixel_width))
642 return icol;
643 }
644 }
645 return -1;
646 }
647
648
649
650 bool noninteractive_need_newline;
651
652
653
654 static bool message_log_need_newline;
655
656
657
658
659 static Lisp_Object message_dolog_marker1;
660 static Lisp_Object message_dolog_marker2;
661 static Lisp_Object message_dolog_marker3;
662
663
664
665
666
667
668 static struct text_pos this_line_start_pos;
669
670
671
672
673 static struct text_pos this_line_end_pos;
674
675
676
677 static int this_line_vpos;
678 static int this_line_y;
679 static int this_line_pixel_height;
680
681
682
683
684 static int this_line_start_x;
685
686
687
688
689
690 static struct text_pos this_line_min_pos;
691
692
693
694 static struct buffer *this_line_buffer;
695
696
697
698 static bool overlay_arrow_seen;
699
700
701
702 static Lisp_Object default_invis_vector[3];
703
704
705
706
707
708 Lisp_Object echo_area_window;
709
710
711
712
713 static Lisp_Object Vmessage_stack;
714
715
716
717
718 static bool message_enable_multibyte;
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 int windows_or_buffers_changed;
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771 int update_mode_lines;
772
773
774
775
776 static bool line_number_displayed;
777
778
779
780
781 Lisp_Object echo_area_buffer[2];
782
783
784
785 static Lisp_Object echo_buffer[2];
786
787
788
789 static Lisp_Object Vwith_echo_area_save_vector;
790
791
792
793
794 static bool display_last_displayed_message_p;
795
796
797
798
799 static bool message_buf_print;
800
801
802
803
804 static bool message_cleared_p;
805
806
807
808
809 #define MAX_SCRATCH_GLYPHS 100
810 static struct glyph_row scratch_glyph_row;
811 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
812
813
814
815 static int last_height;
816
817
818
819 bool help_echo_showing_p;
820
821
822
823
824
825
826
827 #define TEXT_PROP_DISTANCE_LIMIT 100
828
829
830
831
832
833
834
835
836 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
837 do { \
838 if (CACHE) \
839 bidi_unshelve_cache (CACHE, true); \
840 ITCOPY = ITORIG; \
841 CACHE = bidi_shelve_cache (); \
842 } while (false)
843
844 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
845 do { \
846 if (pITORIG != pITCOPY) \
847 *(pITORIG) = *(pITCOPY); \
848 bidi_unshelve_cache (CACHE, false); \
849 CACHE = NULL; \
850 } while (false)
851
852
853 enum { REDISPLAY_SOME = 2};
854
855 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
856 struct font *, bool, int *);
857
858 void
859 redisplay_other_windows (void)
860 {
861 if (!windows_or_buffers_changed)
862 windows_or_buffers_changed = REDISPLAY_SOME;
863 }
864
865 void
866 wset_redisplay (struct window *w)
867 {
868
869 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
870 redisplay_other_windows ();
871 w->redisplay = true;
872 }
873
874 void
875 fset_redisplay (struct frame *f)
876 {
877 redisplay_other_windows ();
878 f->redisplay = true;
879 }
880
881 void
882 bset_redisplay (struct buffer *b)
883 {
884 int count = buffer_window_count (b);
885 if (count > 0)
886 {
887
888 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
889 redisplay_other_windows ();
890
891
892
893 b->text->redisplay = true;
894 }
895 }
896
897 void
898 bset_update_mode_line (struct buffer *b)
899 {
900 if (!update_mode_lines)
901 update_mode_lines = REDISPLAY_SOME;
902 b->text->redisplay = true;
903 }
904
905 void
906 wset_update_mode_line (struct window *w)
907 {
908 w->update_mode_line = true;
909
910
911
912
913
914
915 wset_redisplay (w);
916 }
917
918 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
919 Sset_buffer_redisplay, 4, 4, 0,
920 doc:
921 )
922 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
923 {
924 bset_update_mode_line (current_buffer);
925 current_buffer->prevent_redisplay_optimizations_p = true;
926 return Qnil;
927 }
928
929
930
931
932
933 #ifdef GLYPH_DEBUG
934 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
935 bool trace_redisplay_p;
936 #else
937 enum { trace_redisplay_p = false };
938 #endif
939 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
940 redisplay_trace (char const *fmt, ...)
941 {
942 if (trace_redisplay_p)
943 {
944 va_list ap;
945 va_start (ap, fmt);
946 vprintf (fmt, ap);
947 va_end (ap);
948 }
949 }
950
951 #ifdef DEBUG_TRACE_MOVE
952 extern bool trace_move EXTERNALLY_VISIBLE;
953 bool trace_move;
954 #else
955 enum { trace_move = false };
956 #endif
957 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
958 move_trace (char const *fmt, ...)
959 {
960 if (trace_move)
961 {
962 va_list ap;
963 va_start (ap, fmt);
964 vprintf (fmt, ap);
965 va_end (ap);
966 }
967 }
968
969
970
971 static struct buffer *displayed_buffer;
972
973
974
975 enum prop_handled
976 {
977 HANDLED_NORMALLY,
978 HANDLED_RECOMPUTE_PROPS,
979 HANDLED_OVERLAY_STRING_CONSUMED,
980 HANDLED_RETURN
981 };
982
983
984
985
986 struct props
987 {
988
989 short name;
990
991
992 enum prop_idx idx;
993
994
995
996 enum prop_handled (*handler) (struct it *it);
997 };
998
999 static enum prop_handled handle_face_prop (struct it *);
1000 static enum prop_handled handle_invisible_prop (struct it *);
1001 static enum prop_handled handle_display_prop (struct it *);
1002 static enum prop_handled handle_composition_prop (struct it *);
1003 static enum prop_handled handle_overlay_change (struct it *);
1004 static enum prop_handled handle_fontified_prop (struct it *);
1005
1006
1007
1008 static struct props it_props[] =
1009 {
1010 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
1011
1012
1013 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
1014 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
1015 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
1016 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
1017 {0, 0, NULL}
1018 };
1019
1020
1021
1022 enum move_it_result
1023 {
1024
1025 MOVE_UNDEFINED,
1026
1027
1028 MOVE_POS_MATCH_OR_ZV,
1029
1030
1031 MOVE_X_REACHED,
1032
1033
1034
1035 MOVE_LINE_CONTINUED,
1036
1037
1038
1039 MOVE_LINE_TRUNCATED,
1040
1041
1042 MOVE_NEWLINE_OR_CR
1043 };
1044
1045
1046
1047
1048
1049
1050 #define CLEAR_FACE_CACHE_COUNT 500
1051 static int clear_face_cache_count;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056 #define CLEAR_IMAGE_CACHE_COUNT 101
1057 static int clear_image_cache_count;
1058
1059
1060 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1061 #endif
1062
1063
1064
1065 bool redisplaying_p;
1066
1067
1068
1069
1070
1071
1072
1073
1074 bool display_working_on_window_p;
1075
1076
1077
1078
1079 Lisp_Object help_echo_string;
1080 Lisp_Object help_echo_window;
1081 Lisp_Object help_echo_object;
1082 ptrdiff_t help_echo_pos;
1083
1084
1085
1086 Lisp_Object previous_help_echo_string;
1087
1088
1089
1090 #ifdef HAVE_WINDOW_SYSTEM
1091
1092
1093 static bool hourglass_shown_p;
1094
1095
1096
1097 static struct atimer *hourglass_atimer;
1098
1099 #endif
1100
1101
1102
1103 #define DEFAULT_HOURGLASS_DELAY 1
1104
1105 #ifdef HAVE_WINDOW_SYSTEM
1106
1107
1108 #define THIN_SPACE_WIDTH 1
1109
1110 #endif
1111
1112
1113
1114 static void setup_for_ellipsis (struct it *, int);
1115 static void set_iterator_to_next (struct it *, bool);
1116 static void mark_window_display_accurate_1 (struct window *, bool);
1117 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1118 static bool cursor_row_p (struct glyph_row *);
1119 static int redisplay_mode_lines (Lisp_Object, bool);
1120
1121 static void handle_line_prefix (struct it *);
1122
1123 static void handle_stop_backwards (struct it *, ptrdiff_t);
1124 static void unwind_with_echo_area_buffer (Lisp_Object);
1125 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1126 static bool current_message_1 (void *, Lisp_Object);
1127 static bool truncate_message_1 (void *, Lisp_Object);
1128 static void set_message (Lisp_Object);
1129 static bool set_message_1 (void *, Lisp_Object);
1130 static bool display_echo_area_1 (void *, Lisp_Object);
1131 static bool resize_mini_window_1 (void *, Lisp_Object);
1132 static void unwind_redisplay (void);
1133 static void extend_face_to_end_of_line (struct it *);
1134 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1135 static void push_it (struct it *, struct text_pos *);
1136 static void iterate_out_of_display_property (struct it *);
1137 static void pop_it (struct it *);
1138 static void redisplay_internal (void);
1139 static void echo_area_display (bool);
1140 static void block_buffer_flips (void);
1141 static void unblock_buffer_flips (void);
1142 static void redisplay_windows (Lisp_Object);
1143 static void redisplay_window (Lisp_Object, bool);
1144 static Lisp_Object redisplay_window_error (Lisp_Object);
1145 static Lisp_Object redisplay_window_0 (Lisp_Object);
1146 static Lisp_Object redisplay_window_1 (Lisp_Object);
1147 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1148 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1149 int, int);
1150 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1151 static bool update_menu_bar (struct frame *, bool, bool);
1152 static bool try_window_reusing_current_matrix (struct window *);
1153 static int try_window_id (struct window *);
1154 static void maybe_produce_line_number (struct it *);
1155 static bool should_produce_line_number (struct it *);
1156 static bool display_line (struct it *, int);
1157 static int display_mode_lines (struct window *);
1158 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1159 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1160 Lisp_Object, bool);
1161 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1162 Lisp_Object);
1163 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1164 static void display_menu_bar (struct window *);
1165 static void display_tab_bar (struct window *);
1166 static void update_tab_bar (struct frame *, bool);
1167 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1168 ptrdiff_t *);
1169 static void pint2str (register char *, register int, register ptrdiff_t);
1170
1171 static int display_string (const char *, Lisp_Object, Lisp_Object,
1172 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1173 int);
1174 static void compute_line_metrics (struct it *);
1175 static bool get_overlay_strings (struct it *, ptrdiff_t);
1176 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1177 static void next_overlay_string (struct it *);
1178 static void reseat (struct it *, struct text_pos, bool);
1179 static void reseat_1 (struct it *, struct text_pos, bool);
1180 static bool next_element_from_display_vector (struct it *);
1181 static bool next_element_from_string (struct it *);
1182 static bool next_element_from_c_string (struct it *);
1183 static bool next_element_from_buffer (struct it *);
1184 static bool next_element_from_composition (struct it *);
1185 static bool next_element_from_image (struct it *);
1186 static bool next_element_from_stretch (struct it *);
1187 static bool next_element_from_xwidget (struct it *);
1188 static void load_overlay_strings (struct it *, ptrdiff_t);
1189 static bool get_next_display_element (struct it *);
1190 static enum move_it_result
1191 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1192 enum move_operation_enum);
1193 static void get_visually_first_element (struct it *);
1194 static void compute_stop_pos (struct it *);
1195 static int face_before_or_after_it_pos (struct it *, bool);
1196 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1197 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1198 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1199 Lisp_Object, struct text_pos *,
1200 ptrdiff_t, int, bool, bool);
1201 static int underlying_face_id (const struct it *);
1202
1203 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1204 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1205
1206 #ifdef HAVE_WINDOW_SYSTEM
1207
1208 static void update_tool_bar (struct frame *, bool);
1209 static void gui_draw_bottom_divider (struct window *w);
1210 static void notice_overwritten_cursor (struct window *,
1211 enum glyph_row_area,
1212 int, int, int, int);
1213 static int normal_char_height (struct font *, int);
1214 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1215
1216 static void append_stretch_glyph (struct it *, Lisp_Object,
1217 int, int, int);
1218
1219 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1220 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1221 struct font *, int, bool);
1222 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1223 struct glyph_row *,
1224 struct window *, struct face *,
1225 struct face *);
1226 static void get_cursor_offset_for_mouse_face (struct window *w,
1227 struct glyph_row *row,
1228 int *offset);
1229 #endif
1230
1231 static void produce_special_glyphs (struct it *, enum display_element_type);
1232 static void pad_mode_line (struct it *, bool);
1233 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1234 static bool coords_in_mouse_face_p (struct window *, int, int);
1235 static void reset_box_start_end_flags (struct it *);
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249 int
1250 window_text_bottom_y (struct window *w)
1251 {
1252 int height = WINDOW_PIXEL_HEIGHT (w);
1253
1254 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1255
1256 if (window_wants_mode_line (w))
1257 height -= CURRENT_MODE_LINE_HEIGHT (w);
1258
1259 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1260
1261 return height;
1262 }
1263
1264
1265
1266
1267
1268 int
1269 window_box_width (struct window *w, enum glyph_row_area area)
1270 {
1271 int width = w->pixel_width;
1272
1273 if (!w->pseudo_window_p)
1274 {
1275 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1276 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1277
1278 if (area == TEXT_AREA)
1279 width -= (WINDOW_MARGINS_WIDTH (w)
1280 + WINDOW_FRINGES_WIDTH (w));
1281 else if (area == LEFT_MARGIN_AREA)
1282 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1283 else if (area == RIGHT_MARGIN_AREA)
1284 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1285 }
1286
1287
1288
1289 return max (0, width);
1290 }
1291
1292
1293
1294
1295
1296 int
1297 window_box_height (struct window *w)
1298 {
1299 struct frame *f = XFRAME (w->frame);
1300 int height = WINDOW_PIXEL_HEIGHT (w);
1301
1302 eassert (height >= 0);
1303
1304 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1305 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1306
1307
1308
1309
1310
1311
1312
1313 if (window_wants_mode_line (w))
1314 {
1315 if (w->mode_line_height >= 0)
1316 height -= w->mode_line_height;
1317 else
1318 {
1319 struct glyph_row *ml_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (ml_row && ml_row->mode_line_p)
1324 height -= ml_row->height;
1325 else
1326 height -= estimate_mode_line_height
1327 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1328 }
1329 }
1330
1331 if (window_wants_tab_line (w))
1332 {
1333 if (w->tab_line_height >= 0)
1334 height -= w->tab_line_height;
1335 else
1336 {
1337 struct glyph_row *tl_row
1338 = (w->current_matrix && w->current_matrix->rows
1339 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1340 : 0);
1341 if (tl_row && tl_row->mode_line_p)
1342 height -= tl_row->height;
1343 else
1344 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1345 }
1346 }
1347
1348 if (window_wants_header_line (w))
1349 {
1350 if (w->header_line_height >= 0)
1351 height -= w->header_line_height;
1352 else
1353 {
1354 struct glyph_row *hl_row
1355 = (w->current_matrix && w->current_matrix->rows
1356 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1357 : 0);
1358 if (hl_row && hl_row->mode_line_p)
1359 height -= hl_row->height;
1360 else
1361 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1362 }
1363 }
1364
1365
1366
1367 return max (0, height);
1368 }
1369
1370
1371
1372
1373
1374 int
1375 window_box_left_offset (struct window *w, enum glyph_row_area area)
1376 {
1377 int x;
1378
1379 if (w->pseudo_window_p)
1380 return 0;
1381
1382 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1383
1384 if (area == TEXT_AREA)
1385 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1386 + window_box_width (w, LEFT_MARGIN_AREA));
1387 else if (area == RIGHT_MARGIN_AREA)
1388 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1389 + window_box_width (w, LEFT_MARGIN_AREA)
1390 + window_box_width (w, TEXT_AREA)
1391 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1392 ? 0
1393 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1394 else if (area == LEFT_MARGIN_AREA
1395 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1396 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1397
1398
1399 return min (x, w->pixel_width);
1400 }
1401
1402
1403
1404
1405
1406
1407 static int
1408 window_box_right_offset (struct window *w, enum glyph_row_area area)
1409 {
1410
1411 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1412 w->pixel_width);
1413 }
1414
1415
1416
1417
1418
1419 int
1420 window_box_left (struct window *w, enum glyph_row_area area)
1421 {
1422 struct frame *f = XFRAME (w->frame);
1423 int x;
1424
1425 if (w->pseudo_window_p)
1426 return FRAME_INTERNAL_BORDER_WIDTH (f);
1427
1428 x = (WINDOW_LEFT_EDGE_X (w)
1429 + window_box_left_offset (w, area));
1430
1431 return x;
1432 }
1433
1434
1435
1436
1437
1438
1439 int
1440 window_box_right (struct window *w, enum glyph_row_area area)
1441 {
1442 return window_box_left (w, area) + window_box_width (w, area);
1443 }
1444
1445
1446
1447
1448
1449
1450
1451
1452 void
1453 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1454 int *box_y, int *box_width, int *box_height)
1455 {
1456 if (box_width)
1457 *box_width = window_box_width (w, area);
1458 if (box_height)
1459 *box_height = window_box_height (w);
1460 if (box_x)
1461 *box_x = window_box_left (w, area);
1462 if (box_y)
1463 {
1464 *box_y = WINDOW_TOP_EDGE_Y (w);
1465 if (window_wants_tab_line (w))
1466 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1467 if (window_wants_header_line (w))
1468 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1469 }
1470 }
1471
1472 #ifdef HAVE_WINDOW_SYSTEM
1473
1474
1475
1476
1477
1478
1479
1480
1481 static void
1482 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1483 int *bottom_right_x, int *bottom_right_y)
1484 {
1485 window_box (w, ANY_AREA, top_left_x, top_left_y,
1486 bottom_right_x, bottom_right_y);
1487 *bottom_right_x += *top_left_x;
1488 *bottom_right_y += *top_left_y;
1489 }
1490
1491 #endif
1492
1493
1494
1495
1496
1497
1498
1499
1500 int
1501 line_bottom_y (struct it *it)
1502 {
1503 int line_height = it->max_ascent + it->max_descent;
1504 int line_top_y = it->current_y;
1505
1506 if (line_height == 0)
1507 {
1508 if (last_height)
1509 line_height = last_height;
1510 else if (IT_CHARPOS (*it) < ZV)
1511 {
1512 move_it_by_lines (it, 1);
1513 line_height = (it->max_ascent || it->max_descent
1514 ? it->max_ascent + it->max_descent
1515 : last_height);
1516 }
1517 else
1518 {
1519 struct glyph_row *row = it->glyph_row;
1520
1521
1522 it->glyph_row = NULL;
1523 it->what = IT_CHARACTER;
1524 it->c = ' ';
1525 it->len = 1;
1526 PRODUCE_GLYPHS (it);
1527 line_height = it->ascent + it->descent;
1528 it->glyph_row = row;
1529 }
1530 }
1531
1532 return line_top_y + line_height;
1533 }
1534
1535 DEFUN ("line-pixel-height", Fline_pixel_height,
1536 Sline_pixel_height, 0, 0, 0,
1537 doc:
1538
1539 )
1540 (void)
1541 {
1542 struct it it;
1543 struct text_pos pt;
1544 struct window *w = XWINDOW (selected_window);
1545 struct buffer *old_buffer = NULL;
1546 Lisp_Object result;
1547
1548 if (XBUFFER (w->contents) != current_buffer)
1549 {
1550 old_buffer = current_buffer;
1551 set_buffer_internal_1 (XBUFFER (w->contents));
1552 }
1553 SET_TEXT_POS (pt, PT, PT_BYTE);
1554 void *itdata = bidi_shelve_cache ();
1555 start_display (&it, w, pt);
1556
1557
1558
1559 move_it_by_lines (&it, 0);
1560 it.vpos = it.current_y = 0;
1561 last_height = 0;
1562 result = make_fixnum (line_bottom_y (&it));
1563 if (old_buffer)
1564 set_buffer_internal_1 (old_buffer);
1565
1566 bidi_unshelve_cache (itdata, false);
1567 return result;
1568 }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584 int
1585 default_line_pixel_height (struct window *w)
1586 {
1587 struct frame *f = WINDOW_XFRAME (w);
1588 int height = FRAME_LINE_HEIGHT (f);
1589
1590 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1591 {
1592 struct buffer *b = XBUFFER (w->contents);
1593 Lisp_Object val = BVAR (b, extra_line_spacing);
1594
1595 if (NILP (val))
1596 val = BVAR (&buffer_defaults, extra_line_spacing);
1597 if (!NILP (val))
1598 {
1599 if (RANGED_FIXNUMP (0, val, INT_MAX))
1600 height += XFIXNAT (val);
1601 else if (FLOATP (val))
1602 {
1603 int addon = XFLOAT_DATA (val) * height + 0.5;
1604
1605 if (addon >= 0)
1606 height += addon;
1607 }
1608 }
1609 else
1610 height += f->extra_line_spacing;
1611 }
1612
1613 return height;
1614 }
1615
1616
1617
1618 static Lisp_Object
1619 string_from_display_spec (Lisp_Object spec)
1620 {
1621 if (VECTORP (spec))
1622 {
1623 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1624 if (STRINGP (AREF (spec, i)))
1625 return AREF (spec, i);
1626 }
1627 else
1628 {
1629 for (; CONSP (spec); spec = XCDR (spec))
1630 if (STRINGP (XCAR (spec)))
1631 return XCAR (spec);
1632 }
1633 return spec;
1634 }
1635
1636
1637
1638
1639
1640 static int
1641 window_hscroll_limited (struct window *w, struct frame *f)
1642 {
1643 ptrdiff_t window_hscroll = w->hscroll;
1644 int window_text_width = window_box_width (w, TEXT_AREA);
1645 int colwidth = FRAME_COLUMN_WIDTH (f);
1646
1647 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1648 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1649
1650 return window_hscroll;
1651 }
1652
1653
1654
1655
1656
1657 static void
1658 reset_box_start_end_flags (struct it *it)
1659 {
1660
1661
1662 if (it->area == TEXT_AREA
1663
1664 && !(it->what == IT_IMAGE && it->image_id < 0))
1665 {
1666
1667
1668
1669
1670 if (it->face_box_p)
1671 it->start_of_box_run_p = false;
1672 it->end_of_box_run_p = false;
1673 }
1674 }
1675
1676
1677
1678
1679
1680
1681
1682 bool
1683 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1684 int *rtop, int *rbot, int *rowh, int *vpos)
1685 {
1686 struct it it;
1687 void *itdata = bidi_shelve_cache ();
1688 struct text_pos top;
1689 bool visible_p = false;
1690 struct buffer *old_buffer = NULL;
1691 bool r2l = false;
1692
1693 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1694 return visible_p;
1695
1696 if (XBUFFER (w->contents) != current_buffer)
1697 {
1698 old_buffer = current_buffer;
1699 set_buffer_internal_1 (XBUFFER (w->contents));
1700 }
1701
1702 SET_TEXT_POS_FROM_MARKER (top, w->start);
1703
1704
1705
1706
1707 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1708 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1709
1710
1711
1712 if (charpos >= 0 && CHARPOS (top) > charpos)
1713 return visible_p;
1714
1715
1716
1717
1718
1719
1720
1721
1722 int prev_mode_line_height = w->mode_line_height;
1723 int prev_header_line_height = w->header_line_height;
1724 int prev_tab_line_height = w->tab_line_height;
1725
1726 if (window_wants_mode_line (w))
1727 {
1728 Lisp_Object window_mode_line_format
1729 = window_parameter (w, Qmode_line_format);
1730
1731 w->mode_line_height
1732 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1733 NILP (window_mode_line_format)
1734 ? BVAR (current_buffer, mode_line_format)
1735 : window_mode_line_format);
1736 }
1737
1738 if (window_wants_tab_line (w))
1739 {
1740 Lisp_Object window_tab_line_format
1741 = window_parameter (w, Qtab_line_format);
1742
1743 w->tab_line_height
1744 = display_mode_line (w, TAB_LINE_FACE_ID,
1745 NILP (window_tab_line_format)
1746 ? BVAR (current_buffer, tab_line_format)
1747 : window_tab_line_format);
1748 }
1749
1750 if (window_wants_header_line (w))
1751 {
1752 Lisp_Object window_header_line_format
1753 = window_parameter (w, Qheader_line_format);
1754
1755 w->header_line_height
1756 = display_mode_line (w, HEADER_LINE_FACE_ID,
1757 NILP (window_header_line_format)
1758 ? BVAR (current_buffer, header_line_format)
1759 : window_header_line_format);
1760 }
1761
1762 start_display (&it, w, top);
1763 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1764 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1765
1766
1767
1768 if (!NILP (Vdisplay_line_numbers)
1769 && it.current_x >= it.first_visible_x
1770 && IT_CHARPOS (it) == charpos
1771 && !it.line_number_produced_p)
1772 {
1773
1774
1775
1776 if (!it.lnum_pixel_width)
1777 {
1778 struct it it2;
1779 void *it2data = NULL;
1780
1781 SAVE_IT (it2, it, it2data);
1782 move_it_by_lines (&it, 1);
1783 it2.lnum_pixel_width = it.lnum_pixel_width;
1784 RESTORE_IT (&it, &it2, it2data);
1785 }
1786 it.current_x += it.lnum_pixel_width;
1787 }
1788
1789 if (charpos >= 0
1790 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1791 && IT_CHARPOS (it) >= charpos)
1792
1793
1794
1795 || (it.bidi_p && it.bidi_it.scan_dir == -1
1796 && IT_CHARPOS (it) <= charpos)))
1797 {
1798
1799
1800
1801
1802
1803
1804 int top_x = it.current_x;
1805 int top_y = it.current_y;
1806 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1807 int bottom_y;
1808 struct it save_it;
1809 void *save_it_data = NULL;
1810
1811
1812 SAVE_IT (save_it, it, save_it_data);
1813 last_height = 0;
1814 bottom_y = line_bottom_y (&it);
1815 if (top_y < window_top_y)
1816 visible_p = bottom_y > window_top_y;
1817 else if (top_y < it.last_visible_y)
1818 visible_p = true;
1819 if (bottom_y >= it.last_visible_y
1820 && it.bidi_p && it.bidi_it.scan_dir == -1
1821 && IT_CHARPOS (it) < charpos)
1822 {
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833 int ten_more_lines = 10 * default_line_pixel_height (w);
1834
1835 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1836 MOVE_TO_POS | MOVE_TO_Y);
1837 if (it.current_y > top_y)
1838 visible_p = false;
1839
1840 }
1841 RESTORE_IT (&it, &save_it, save_it_data);
1842 if (visible_p)
1843 {
1844 if (it.method == GET_FROM_DISPLAY_VECTOR)
1845 {
1846
1847
1848 if (charpos < 2 || top.charpos >= charpos)
1849 top_x = it.glyph_row->x;
1850 else
1851 {
1852 struct it it2, it2_prev;
1853
1854
1855
1856
1857
1858
1859 start_display (&it2, w, top);
1860 it2.glyph_row = NULL;
1861 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1862
1863
1864
1865
1866 if (IT_CHARPOS (it2) != charpos - 1)
1867 it2_prev = it2;
1868 else
1869 {
1870
1871
1872
1873 do {
1874 get_next_display_element (&it2);
1875 PRODUCE_GLYPHS (&it2);
1876 it2_prev = it2;
1877 set_iterator_to_next (&it2, true);
1878 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1879 && IT_CHARPOS (it2) < charpos);
1880 }
1881 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1882 || it2_prev.current_x > it2_prev.last_visible_x)
1883 top_x = it.glyph_row->x;
1884 else
1885 {
1886 top_x = it2_prev.current_x;
1887 top_y = it2_prev.current_y;
1888 }
1889 }
1890 }
1891 else if (IT_CHARPOS (it) != charpos)
1892 {
1893 Lisp_Object cpos = make_fixnum (charpos);
1894 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1895 Lisp_Object string = string_from_display_spec (spec);
1896 struct text_pos tpos;
1897 bool newline_in_string
1898 = (STRINGP (string)
1899 && memchr (SDATA (string), '\n', SBYTES (string)));
1900
1901 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1902 bool replacing_spec_p
1903 = (!NILP (spec)
1904 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1905 charpos, FRAME_WINDOW_P (it.f)));
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 if (replacing_spec_p)
1923 {
1924 Lisp_Object startpos, endpos;
1925 EMACS_INT start, end;
1926 struct it it3;
1927
1928
1929
1930 endpos =
1931 Fnext_single_char_property_change (cpos, Qdisplay,
1932 Qnil, Qnil);
1933 startpos =
1934 Fprevious_single_char_property_change (endpos, Qdisplay,
1935 Qnil, Qnil);
1936 start = XFIXNAT (startpos);
1937 end = XFIXNAT (endpos);
1938
1939
1940 start_display (&it3, w, top);
1941 if (start > CHARPOS (top))
1942 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1943
1944
1945
1946
1947 if (it3.method == GET_FROM_BUFFER
1948 && (it3.c == '\n'
1949 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1950 move_it_by_lines (&it3, 1);
1951 else if (move_it_in_display_line_to (&it3, -1,
1952 it3.current_x
1953 + it3.pixel_width,
1954 MOVE_TO_X)
1955 == MOVE_LINE_CONTINUED)
1956 {
1957 move_it_by_lines (&it3, 1);
1958
1959
1960
1961 if (it3.line_wrap == WORD_WRAP)
1962 move_it_by_lines (&it3, -1);
1963 }
1964
1965
1966
1967 top_y = it3.current_y;
1968 if (it3.bidi_p)
1969 {
1970
1971
1972
1973
1974
1975 start_display (&it3, w, top);
1976 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1977 if (it3.current_y < top_y)
1978 top_y = it3.current_y;
1979 }
1980
1981
1982
1983 start_display (&it3, w, top);
1984 it3.glyph_row = NULL;
1985 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1986
1987
1988
1989
1990
1991
1992
1993 bool it3_moved = false;
1994 int top_x_before_string = it3.current_x;
1995
1996
1997
1998
1999
2000 while (get_next_display_element (&it3))
2001 {
2002 if (!EQ (it3.object, string))
2003 top_x_before_string = it3.current_x;
2004 PRODUCE_GLYPHS (&it3);
2005 if ((it3.bidi_it.scan_dir == 1
2006 && IT_CHARPOS (it3) >= charpos)
2007 || (it3.bidi_it.scan_dir == -1
2008 && IT_CHARPOS (it3) <= charpos)
2009 || ITERATOR_AT_END_OF_LINE_P (&it3))
2010 break;
2011 it3_moved = true;
2012 set_iterator_to_next (&it3, false);
2013 }
2014 top_x = it3.current_x - it3.pixel_width;
2015
2016
2017
2018 if (!it3.line_number_produced_p)
2019 {
2020 if (it3.lnum_pixel_width > 0)
2021 {
2022 top_x += it3.lnum_pixel_width;
2023 top_x_before_string += it3.lnum_pixel_width;
2024 }
2025 else if (it.line_number_produced_p)
2026 {
2027 top_x += it.lnum_pixel_width;
2028 top_x_before_string += it3.lnum_pixel_width;
2029 }
2030 }
2031
2032
2033
2034
2035
2036
2037 if (it3_moved
2038 && newline_in_string
2039 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2040 top_x = top_x_before_string;
2041 }
2042 }
2043
2044 *x = top_x;
2045
2046
2047
2048
2049 if (it.ascent == 0 && it.what == IT_IMAGE
2050 && it.method != GET_FROM_IMAGE
2051 && it.image_id < 0
2052 && it.max_ascent > 0)
2053 *y = max (top_y, window_top_y);
2054 else
2055 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2056 *rtop = max (0, window_top_y - top_y);
2057 *rbot = max (0, bottom_y - it.last_visible_y);
2058 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2059 - max (top_y, window_top_y)));
2060 *vpos = it.vpos;
2061 if (it.bidi_it.paragraph_dir == R2L)
2062 r2l = true;
2063 }
2064 }
2065 else
2066 {
2067
2068
2069
2070 struct it it2;
2071 void *it2data = NULL;
2072
2073 SAVE_IT (it2, it, it2data);
2074 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2075 move_it_by_lines (&it, 1);
2076 if (charpos < IT_CHARPOS (it)
2077 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2078 {
2079 visible_p = true;
2080 RESTORE_IT (&it2, &it2, it2data);
2081 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2082 *x = it2.current_x;
2083 if (it2.ascent == 0 && it2.what == IT_IMAGE
2084 && it2.method != GET_FROM_IMAGE
2085 && it2.image_id < 0
2086 && it2.max_ascent > 0)
2087 *y = it2.current_y;
2088 else
2089 *y = it2.current_y + it2.max_ascent - it2.ascent;
2090 *rtop = max (0, -it2.current_y);
2091 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2092 - it.last_visible_y));
2093 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2094 it.last_visible_y)
2095 - max (max (it2.current_y,
2096 WINDOW_TAB_LINE_HEIGHT (w)),
2097 WINDOW_HEADER_LINE_HEIGHT (w))));
2098 *vpos = it2.vpos;
2099 if (it2.bidi_it.paragraph_dir == R2L)
2100 r2l = true;
2101 }
2102 else
2103 bidi_unshelve_cache (it2data, true);
2104 }
2105 bidi_unshelve_cache (itdata, false);
2106
2107 if (old_buffer)
2108 set_buffer_internal_1 (old_buffer);
2109
2110 if (visible_p)
2111 {
2112 if (w->hscroll > 0)
2113 *x -=
2114 window_hscroll_limited (w, WINDOW_XFRAME (w))
2115 * WINDOW_FRAME_COLUMN_WIDTH (w);
2116
2117
2118
2119
2120
2121 if (r2l)
2122 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2123 }
2124
2125 #if false
2126
2127 if (visible_p)
2128 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2129 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2130 else
2131 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2132 #endif
2133
2134
2135 w->mode_line_height = prev_mode_line_height;
2136 w->header_line_height = prev_header_line_height;
2137 w->tab_line_height = prev_tab_line_height;
2138
2139 return visible_p;
2140 }
2141
2142
2143
2144
2145
2146
2147
2148 static int
2149 check_char_and_length (const unsigned char *str, int *len)
2150 {
2151 int c = string_char_and_length (str, len);
2152 if (!CHAR_VALID_P (c))
2153
2154
2155
2156 c = '?';
2157
2158 return c;
2159 }
2160
2161
2162
2163
2164
2165
2166 static struct text_pos
2167 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2168 {
2169 eassert (STRINGP (string) && nchars >= 0);
2170
2171 if (STRING_MULTIBYTE (string))
2172 {
2173 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2174
2175 while (nchars--)
2176 {
2177 int len = BYTES_BY_CHAR_HEAD (*p);
2178 p += len;
2179 CHARPOS (pos) += 1;
2180 BYTEPOS (pos) += len;
2181 }
2182 }
2183 else
2184 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2185
2186 return pos;
2187 }
2188
2189
2190
2191
2192
2193 static struct text_pos
2194 string_pos (ptrdiff_t charpos, Lisp_Object string)
2195 {
2196 struct text_pos pos;
2197 eassert (STRINGP (string));
2198 eassert (charpos >= 0);
2199 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2200 return pos;
2201 }
2202
2203
2204
2205
2206
2207
2208 static struct text_pos
2209 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2210 {
2211 struct text_pos pos;
2212
2213 eassert (s != NULL);
2214 eassert (charpos >= 0);
2215
2216 if (multibyte_p)
2217 {
2218 SET_TEXT_POS (pos, 0, 0);
2219 while (charpos--)
2220 {
2221 int len = BYTES_BY_CHAR_HEAD (*s);
2222 s += len;
2223 CHARPOS (pos) += 1;
2224 BYTEPOS (pos) += len;
2225 }
2226 }
2227 else
2228 SET_TEXT_POS (pos, charpos, charpos);
2229
2230 return pos;
2231 }
2232
2233
2234
2235
2236
2237 static ptrdiff_t
2238 number_of_chars (const char *s, bool multibyte_p)
2239 {
2240 ptrdiff_t nchars;
2241
2242 if (multibyte_p)
2243 {
2244 ptrdiff_t rest = strlen (s);
2245 const unsigned char *p = (const unsigned char *) s;
2246
2247 for (nchars = 0; rest > 0; ++nchars)
2248 {
2249 int len = BYTES_BY_CHAR_HEAD (*p);
2250 rest -= len, p += len;
2251 }
2252 }
2253 else
2254 nchars = strlen (s);
2255
2256 return nchars;
2257 }
2258
2259
2260
2261
2262
2263
2264 static void
2265 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2266 {
2267 eassert (STRINGP (string));
2268 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2269
2270 if (STRING_MULTIBYTE (string))
2271 *newpos = string_pos_nchars_ahead (pos, string,
2272 CHARPOS (*newpos) - CHARPOS (pos));
2273 else
2274 BYTEPOS (*newpos) = CHARPOS (*newpos);
2275 }
2276
2277
2278
2279
2280
2281 int
2282 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2283 {
2284 #ifdef HAVE_WINDOW_SYSTEM
2285 if (FRAME_WINDOW_P (f))
2286 {
2287 int height = FONT_HEIGHT (FRAME_FONT (f));
2288
2289
2290
2291 if (FRAME_FACE_CACHE (f))
2292 {
2293 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2294 if (face)
2295 {
2296 if (face->font)
2297 height = normal_char_height (face->font, -1);
2298 if (face->box_horizontal_line_width > 0)
2299 height += 2 * face->box_horizontal_line_width;
2300 }
2301 }
2302
2303 return height;
2304 }
2305 #endif
2306
2307 return 1;
2308 }
2309
2310
2311
2312
2313
2314
2315 void
2316 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2317 NativeRectangle *bounds, bool noclip)
2318 {
2319
2320 #ifdef HAVE_WINDOW_SYSTEM
2321 if (FRAME_WINDOW_P (f))
2322 {
2323
2324
2325 if (pix_x < 0)
2326 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2327 if (pix_y < 0)
2328 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2329
2330 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2331 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2332
2333 if (bounds)
2334 STORE_NATIVE_RECT (*bounds,
2335 FRAME_COL_TO_PIXEL_X (f, pix_x),
2336 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2337 FRAME_COLUMN_WIDTH (f) - 1,
2338 FRAME_LINE_HEIGHT (f) - 1);
2339
2340
2341 if (!noclip)
2342 {
2343 if (pix_x < 0)
2344 pix_x = 0;
2345 else if (pix_x > FRAME_TOTAL_COLS (f))
2346 pix_x = FRAME_TOTAL_COLS (f);
2347
2348 if (pix_y < 0)
2349 pix_y = 0;
2350 else if (pix_y > FRAME_TOTAL_LINES (f))
2351 pix_y = FRAME_TOTAL_LINES (f);
2352 }
2353 }
2354 #endif
2355
2356 *x = pix_x;
2357 *y = pix_y;
2358 }
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369 struct glyph *
2370 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2371 int *dx, int *dy, int *area)
2372 {
2373 struct glyph *glyph, *end;
2374 struct glyph_row *row = NULL;
2375 int x0, i;
2376
2377
2378 for (i = 0; i < w->current_matrix->nrows; ++i)
2379 {
2380 row = MATRIX_ROW (w->current_matrix, i);
2381 if (!row->enabled_p)
2382 return NULL;
2383 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2384 break;
2385 }
2386
2387 *vpos = i;
2388 *hpos = 0;
2389
2390
2391 if (i == w->current_matrix->nrows)
2392 return NULL;
2393
2394
2395 if (w->pseudo_window_p)
2396 {
2397 *area = TEXT_AREA;
2398 x0 = 0;
2399 }
2400 else
2401 {
2402 if (x < window_box_left_offset (w, TEXT_AREA))
2403 {
2404 *area = LEFT_MARGIN_AREA;
2405 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2406 }
2407 else if (x < window_box_right_offset (w, TEXT_AREA))
2408 {
2409 *area = TEXT_AREA;
2410 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2411 }
2412 else
2413 {
2414 *area = RIGHT_MARGIN_AREA;
2415 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2416 }
2417 }
2418
2419
2420 glyph = row->glyphs[*area];
2421 end = glyph + row->used[*area];
2422 x -= x0;
2423 while (glyph < end && x >= glyph->pixel_width)
2424 {
2425 x -= glyph->pixel_width;
2426 ++glyph;
2427 }
2428
2429 if (glyph == end)
2430 return NULL;
2431
2432 if (dx)
2433 {
2434 *dx = x;
2435 *dy = y - (row->y + row->ascent - glyph->ascent);
2436 }
2437
2438 *hpos = glyph - row->glyphs[*area];
2439 return glyph;
2440 }
2441
2442
2443
2444
2445 static void
2446 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2447 {
2448 if (w->pseudo_window_p)
2449 {
2450
2451
2452 struct frame *f = XFRAME (w->frame);
2453 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2454 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2455 }
2456 else
2457 {
2458 *x -= WINDOW_LEFT_EDGE_X (w);
2459 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2460 }
2461 }
2462
2463 #ifdef HAVE_WINDOW_SYSTEM
2464
2465
2466
2467
2468
2469 int
2470 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2471 {
2472 Emacs_Rectangle r;
2473
2474 if (n <= 0)
2475 return 0;
2476
2477 if (s->row->full_width_p)
2478 {
2479
2480 r.x = WINDOW_LEFT_EDGE_X (s->w);
2481 if (s->row->mode_line_p)
2482 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2483 else
2484 r.width = WINDOW_PIXEL_WIDTH (s->w);
2485
2486
2487
2488 if (s->w->pseudo_window_p)
2489 r.height = s->row->visible_height;
2490 else
2491 r.height = s->height;
2492 }
2493 else
2494 {
2495
2496 r.x = window_box_left (s->w, s->area);
2497 r.width = window_box_width (s->w, s->area);
2498 r.height = s->row->visible_height;
2499 }
2500
2501 if (s->clip_head)
2502 if (r.x < s->clip_head->x)
2503 {
2504 if (r.width >= s->clip_head->x - r.x)
2505 r.width -= s->clip_head->x - r.x;
2506 else
2507 r.width = 0;
2508 r.x = s->clip_head->x;
2509 }
2510 if (s->clip_tail)
2511 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2512 {
2513 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2514 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2515 else
2516 r.width = 0;
2517 }
2518
2519
2520
2521
2522 if (s->for_overlaps)
2523 {
2524 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2525 r.height = window_text_bottom_y (s->w) - r.y;
2526
2527
2528
2529
2530
2531
2532 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2533 {
2534 Emacs_Rectangle rc, r_save = r;
2535
2536 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2537 rc.y = s->w->phys_cursor.y;
2538 rc.width = s->w->phys_cursor_width;
2539 rc.height = s->w->phys_cursor_height;
2540
2541 gui_intersect_rectangles (&r_save, &rc, &r);
2542 }
2543 }
2544 else
2545 {
2546
2547
2548
2549 if (!s->row->full_width_p
2550 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2551 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2552 else
2553 r.y = max (0, s->row->y);
2554 }
2555
2556 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2557
2558
2559
2560 if (s->hl == DRAW_CURSOR)
2561 {
2562 struct glyph *glyph = s->first_glyph;
2563 int height, max_y;
2564
2565 if (s->x > r.x)
2566 {
2567 if (r.width >= s->x - r.x)
2568 r.width -= s->x - r.x;
2569 else
2570 r.width = 0;
2571 r.x = s->x;
2572 }
2573 r.width = min (r.width, glyph->pixel_width);
2574
2575
2576 height = min (glyph->ascent + glyph->descent,
2577 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2578 max_y = window_text_bottom_y (s->w) - height;
2579 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2580 if (s->ybase - glyph->ascent > max_y)
2581 {
2582 r.y = max_y;
2583 r.height = height;
2584 }
2585 else
2586 {
2587
2588 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2589 if (height < r.height)
2590 {
2591 max_y = r.y + r.height;
2592 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2593 r.height = min (max_y - r.y, height);
2594 }
2595 }
2596 }
2597
2598 if (s->row->clip)
2599 {
2600 Emacs_Rectangle r_save = r;
2601
2602 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2603 r.width = 0;
2604 }
2605
2606 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2607 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2608 {
2609 #ifdef CONVERT_FROM_EMACS_RECT
2610 CONVERT_FROM_EMACS_RECT (r, *rects);
2611 #else
2612 *rects = r;
2613 #endif
2614 return 1;
2615 }
2616 else
2617 {
2618
2619
2620
2621
2622 #ifdef CONVERT_FROM_EMACS_RECT
2623 Emacs_Rectangle rs[2];
2624 #else
2625 Emacs_Rectangle *rs = rects;
2626 #endif
2627 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2628
2629 if (s->for_overlaps & OVERLAPS_PRED)
2630 {
2631 rs[i] = r;
2632 if (r.y + r.height > row_y)
2633 {
2634 if (r.y < row_y)
2635 rs[i].height = row_y - r.y;
2636 else
2637 rs[i].height = 0;
2638 }
2639 i++;
2640 }
2641 if (s->for_overlaps & OVERLAPS_SUCC)
2642 {
2643 rs[i] = r;
2644 if (r.y < row_y + s->row->visible_height)
2645 {
2646 if (r.y + r.height > row_y + s->row->visible_height)
2647 {
2648 rs[i].y = row_y + s->row->visible_height;
2649 rs[i].height = r.y + r.height - rs[i].y;
2650 }
2651 else
2652 rs[i].height = 0;
2653 }
2654 i++;
2655 }
2656
2657 n = i;
2658 #ifdef CONVERT_FROM_EMACS_RECT
2659 for (i = 0; i < n; i++)
2660 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2661 #endif
2662 return n;
2663 }
2664 }
2665
2666
2667
2668
2669 void
2670 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2671 {
2672 get_glyph_string_clip_rects (s, nr, 1);
2673 }
2674
2675
2676
2677
2678
2679
2680
2681 void
2682 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2683 struct glyph *glyph, int *xp, int *yp, int *heightp)
2684 {
2685 struct frame *f = XFRAME (WINDOW_FRAME (w));
2686 int x, y, wd, h, h0, y0, ascent;
2687
2688
2689
2690
2691
2692 wd = glyph->pixel_width;
2693
2694 x = w->phys_cursor.x;
2695 if (x < 0)
2696 {
2697 wd += x;
2698 x = 0;
2699 }
2700
2701 if (glyph->type == STRETCH_GLYPH
2702 && !x_stretch_cursor_p)
2703 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2704 w->phys_cursor_width = wd;
2705
2706
2707
2708 y = w->phys_cursor.y;
2709 ascent = row->ascent;
2710
2711
2712
2713 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2714 {
2715 y -= glyph->ascent - row->ascent;
2716 ascent = glyph->ascent;
2717 }
2718
2719
2720 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2721
2722 h = max (h0, ascent + glyph->descent);
2723
2724
2725 h = min (h, row->height);
2726 h0 = min (h0, ascent + glyph->descent);
2727
2728 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2729 if (y < y0)
2730 {
2731 h = max (h - (y0 - y) + 1, h0);
2732 y = y0 - 1;
2733 }
2734 else
2735 {
2736 y0 = window_text_bottom_y (w) - h0;
2737 if (y > y0)
2738 {
2739 h += y - y0;
2740 y = y0;
2741 }
2742 }
2743
2744 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2745 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2746 *heightp = h;
2747 }
2748
2749
2750
2751
2752
2753 void
2754 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2755 {
2756 Lisp_Object window;
2757 struct window *w;
2758 struct glyph_row *r, *gr, *end_row;
2759 enum window_part part;
2760 enum glyph_row_area area;
2761 int x, y, width, height;
2762
2763 if (mouse_fine_grained_tracking)
2764 {
2765 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2766 return;
2767 }
2768
2769
2770
2771
2772 if (window_resize_pixelwise)
2773 {
2774 width = height = 1;
2775 goto virtual_glyph;
2776 }
2777 else if (!f->glyphs_initialized_p
2778 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2779 NILP (window)))
2780 {
2781 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2782 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2783 goto virtual_glyph;
2784 }
2785
2786 w = XWINDOW (window);
2787 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2788 height = WINDOW_FRAME_LINE_HEIGHT (w);
2789
2790 x = window_relative_x_coord (w, part, gx);
2791 y = gy - WINDOW_TOP_EDGE_Y (w);
2792
2793 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2794 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2795
2796 if (w->pseudo_window_p)
2797 {
2798 area = TEXT_AREA;
2799 part = ON_MODE_LINE;
2800 goto text_glyph;
2801 }
2802
2803 switch (part)
2804 {
2805 case ON_LEFT_MARGIN:
2806 area = LEFT_MARGIN_AREA;
2807 goto text_glyph;
2808
2809 case ON_RIGHT_MARGIN:
2810 area = RIGHT_MARGIN_AREA;
2811 goto text_glyph;
2812
2813 case ON_TAB_LINE:
2814 case ON_HEADER_LINE:
2815 case ON_MODE_LINE:
2816 gr = (part == ON_TAB_LINE
2817 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2818 : (part == ON_HEADER_LINE
2819 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2820 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2821 gy = gr->y;
2822 area = TEXT_AREA;
2823 goto text_glyph_row_found;
2824
2825 case ON_TEXT:
2826 area = TEXT_AREA;
2827
2828 text_glyph:
2829 gr = 0; gy = 0;
2830 for (; r <= end_row && r->enabled_p; ++r)
2831 if (r->y + r->height > y)
2832 {
2833 gr = r; gy = r->y;
2834 break;
2835 }
2836
2837 text_glyph_row_found:
2838 if (gr && gy <= y)
2839 {
2840 struct glyph *g = gr->glyphs[area];
2841 struct glyph *end = g + gr->used[area];
2842
2843 height = gr->height;
2844 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2845 if (gx + g->pixel_width > x)
2846 break;
2847
2848 if (g < end)
2849 {
2850 if (g->type == IMAGE_GLYPH)
2851 {
2852
2853
2854 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2855 return;
2856 }
2857 width = g->pixel_width;
2858 }
2859 else
2860 {
2861
2862 x -= gx;
2863 gx += (x / width) * width;
2864 }
2865
2866 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2867 && part != ON_TAB_LINE)
2868 {
2869 gx += window_box_left_offset (w, area);
2870
2871
2872 height = min (height,
2873 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2874 }
2875 }
2876 else
2877 {
2878
2879 gx = (x / width) * width;
2880 y -= gy;
2881 gy += (y / height) * height;
2882 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2883 && part != ON_TAB_LINE)
2884
2885 height = min (height,
2886 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2887 }
2888 break;
2889
2890 case ON_LEFT_FRINGE:
2891 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2892 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2893 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2894 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2895 goto row_glyph;
2896
2897 case ON_RIGHT_FRINGE:
2898 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2899 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2900 : window_box_right_offset (w, TEXT_AREA));
2901 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2902 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2903 && !WINDOW_RIGHTMOST_P (w))
2904 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2905
2906
2907 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2908 else
2909 width = WINDOW_PIXEL_WIDTH (w) - gx;
2910 else
2911 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2912
2913 goto row_glyph;
2914
2915 case ON_VERTICAL_BORDER:
2916 gx = WINDOW_PIXEL_WIDTH (w) - width;
2917 goto row_glyph;
2918
2919 case ON_VERTICAL_SCROLL_BAR:
2920 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2921 ? 0
2922 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2923 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2924 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2925 : 0)));
2926 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2927
2928 row_glyph:
2929 gr = 0, gy = 0;
2930 for (; r <= end_row && r->enabled_p; ++r)
2931 if (r->y + r->height > y)
2932 {
2933 gr = r; gy = r->y;
2934 break;
2935 }
2936
2937 if (gr && gy <= y)
2938 height = gr->height;
2939 else
2940 {
2941
2942 y -= gy;
2943 gy += (y / height) * height;
2944 }
2945 break;
2946
2947 case ON_RIGHT_DIVIDER:
2948 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2949 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2950 gy = 0;
2951
2952 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2953 goto add_edge;
2954
2955 case ON_BOTTOM_DIVIDER:
2956 gx = 0;
2957 width = WINDOW_PIXEL_WIDTH (w);
2958 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2959 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2960 goto add_edge;
2961
2962 default:
2963 ;
2964 virtual_glyph:
2965
2966
2967
2968
2969
2970
2971 if (gx < 0)
2972 gx -= width - 1;
2973 if (gy < 0)
2974 gy -= height - 1;
2975
2976 gx = (gx / width) * width;
2977 gy = (gy / height) * height;
2978
2979 goto store_rect;
2980 }
2981
2982 add_edge:
2983 gx += WINDOW_LEFT_EDGE_X (w);
2984 gy += WINDOW_TOP_EDGE_Y (w);
2985
2986 store_rect:
2987 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2988
2989
2990 #if false && defined HAVE_X_WINDOWS
2991 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2992 f->output_data.x->normal_gc,
2993 gx, gy, width, height);
2994 #endif
2995 }
2996
2997
2998 #endif
2999
3000 static void
3001 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
3002 {
3003 eassert (w);
3004 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
3005 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
3006 w->window_end_vpos
3007 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
3008 }
3009
3010 static bool
3011 hscrolling_current_line_p (struct window *w)
3012 {
3013 return (!w->suspend_auto_hscroll
3014 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
3015 Qcurrent_line));
3016 }
3017
3018
3019
3020
3021
3022
3023
3024 static Lisp_Object
3025 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
3026 {
3027 add_to_log ("Error during redisplay: %S signaled %S",
3028 Flist (nargs, args), arg);
3029 return Qnil;
3030 }
3031
3032
3033
3034
3035
3036 static Lisp_Object
3037 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3038 {
3039 Lisp_Object val;
3040
3041 if (inhibit_eval_during_redisplay)
3042 val = Qnil;
3043 else
3044 {
3045 ptrdiff_t i;
3046 specpdl_ref count = SPECPDL_INDEX ();
3047 Lisp_Object *args;
3048 USE_SAFE_ALLOCA;
3049 SAFE_ALLOCA_LISP (args, nargs);
3050
3051 args[0] = func;
3052 for (i = 1; i < nargs; i++)
3053 args[i] = va_arg (ap, Lisp_Object);
3054
3055 specbind (Qinhibit_redisplay, Qt);
3056 if (inhibit_quit)
3057 specbind (Qinhibit_quit, Qt);
3058
3059
3060 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3061 safe_eval_handler);
3062 val = SAFE_FREE_UNBIND_TO (count, val);
3063 }
3064
3065 return val;
3066 }
3067
3068 Lisp_Object
3069 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3070 {
3071 Lisp_Object retval;
3072 va_list ap;
3073
3074 va_start (ap, func);
3075 retval = safe__call (false, nargs, func, ap);
3076 va_end (ap);
3077 return retval;
3078 }
3079
3080
3081
3082
3083 Lisp_Object
3084 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3085 {
3086 return safe_call (2, fn, arg);
3087 }
3088
3089 static Lisp_Object
3090 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3091 {
3092 Lisp_Object retval;
3093 va_list ap;
3094
3095 va_start (ap, fn);
3096 retval = safe__call (inhibit_quit, 2, fn, ap);
3097 va_end (ap);
3098 return retval;
3099 }
3100
3101 Lisp_Object
3102 safe_eval (Lisp_Object sexpr)
3103 {
3104 return safe__call1 (false, Qeval, sexpr);
3105 }
3106
3107 static Lisp_Object
3108 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3109 {
3110 return safe__call1 (inhibit_quit, Qeval, sexpr);
3111 }
3112
3113
3114
3115
3116 Lisp_Object
3117 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3118 {
3119 return safe_call (3, fn, arg1, arg2);
3120 }
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131 static void
3132 CHECK_IT (struct it *it)
3133 {
3134 #if false
3135 if (it->method == GET_FROM_STRING)
3136 {
3137 eassert (STRINGP (it->string));
3138 eassert (IT_STRING_CHARPOS (*it) >= 0);
3139 }
3140 else
3141 {
3142 eassert (IT_STRING_CHARPOS (*it) < 0);
3143 if (it->method == GET_FROM_BUFFER)
3144 {
3145
3146 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3147 }
3148 }
3149
3150 if (it->dpvec)
3151 eassert (it->current.dpvec_index >= 0);
3152 else
3153 eassert (it->current.dpvec_index < 0);
3154 #endif
3155 }
3156
3157
3158
3159
3160
3161 static void
3162 CHECK_WINDOW_END (struct window *w)
3163 {
3164 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3165 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3166 {
3167 struct glyph_row *row;
3168 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3169 !row->enabled_p
3170 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3171 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3172 }
3173 #endif
3174 }
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199 void
3200 init_iterator (struct it *it, struct window *w,
3201 ptrdiff_t charpos, ptrdiff_t bytepos,
3202 struct glyph_row *row, enum face_id base_face_id)
3203 {
3204 enum face_id remapped_base_face_id = base_face_id;
3205 int body_width = 0, body_height = 0;
3206
3207
3208 eassert (w != NULL && it != NULL);
3209 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3210 && charpos <= ZV));
3211
3212
3213
3214
3215
3216 if (!inhibit_free_realized_faces)
3217 {
3218 if (face_change)
3219 {
3220 face_change = false;
3221 XFRAME (w->frame)->face_change = 0;
3222 free_all_realized_faces (Qnil);
3223 }
3224 else if (XFRAME (w->frame)->face_change)
3225 {
3226 XFRAME (w->frame)->face_change = 0;
3227 free_all_realized_faces (w->frame);
3228 }
3229 }
3230
3231
3232 if (! NILP (Vface_remapping_alist))
3233 remapped_base_face_id
3234 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3235
3236
3237
3238 if (row == NULL)
3239 {
3240 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3241 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3242 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3243 else if (base_face_id == TAB_LINE_FACE_ID)
3244 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3245 else if (base_face_id == HEADER_LINE_FACE_ID)
3246 {
3247
3248 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3249 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3250 }
3251 }
3252
3253
3254
3255 memclear (it, sizeof *it);
3256 it->current.overlay_string_index = -1;
3257 it->current.dpvec_index = -1;
3258 it->base_face_id = remapped_base_face_id;
3259 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3260 it->paragraph_embedding = L2R;
3261 it->bidi_it.w = w;
3262
3263
3264 XSETWINDOW (it->window, w);
3265 it->w = w;
3266 it->f = XFRAME (w->frame);
3267
3268 it->cmp_it.id = -1;
3269 it->cmp_it.parent_it = it;
3270
3271 if (max_redisplay_ticks > 0)
3272 update_redisplay_ticks (0, w);
3273
3274
3275 if (base_face_id == DEFAULT_FACE_ID
3276 && FRAME_WINDOW_P (it->f))
3277 {
3278 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3279 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3280 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3281 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3282 * FRAME_LINE_HEIGHT (it->f));
3283 else if (it->f->extra_line_spacing > 0)
3284 it->extra_line_spacing = it->f->extra_line_spacing;
3285 }
3286
3287
3288
3289
3290
3291 if (FRAME_FACE_CACHE (it->f) == NULL)
3292 init_frame_faces (it->f);
3293 if (FRAME_FACE_CACHE (it->f)->used == 0)
3294 recompute_basic_faces (it->f);
3295
3296 it->override_ascent = -1;
3297
3298
3299 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3300
3301
3302
3303
3304 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3305 ? (clip_to_bounds
3306 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3307 PTRDIFF_MAX))
3308 : (!NILP (BVAR (current_buffer, selective_display))
3309 ? -1 : 0));
3310 it->selective_display_ellipsis_p
3311 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3312
3313
3314 it->dp = window_display_table (w);
3315
3316
3317 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3318
3319 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3320
3321
3322 if (TRUNCATE != 0)
3323 it->line_wrap = TRUNCATE;
3324 if (base_face_id == DEFAULT_FACE_ID
3325 && !it->w->hscroll
3326 && (WINDOW_FULL_WIDTH_P (it->w)
3327 || NILP (Vtruncate_partial_width_windows)
3328 || (FIXNUMP (Vtruncate_partial_width_windows)
3329
3330 && (XFIXNUM (Vtruncate_partial_width_windows)
3331 <= WINDOW_TOTAL_COLS (it->w))))
3332 && NILP (BVAR (current_buffer, truncate_lines)))
3333 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3334 ? WINDOW_WRAP : WORD_WRAP;
3335
3336
3337
3338
3339
3340
3341
3342 #ifdef HAVE_WINDOW_SYSTEM
3343 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3344 #endif
3345 {
3346 if (it->line_wrap == TRUNCATE)
3347 {
3348
3349 eassert (it->glyph_row == NULL);
3350 produce_special_glyphs (it, IT_TRUNCATION);
3351 it->truncation_pixel_width = it->pixel_width;
3352 }
3353 else
3354 {
3355
3356 eassert (it->glyph_row == NULL);
3357 produce_special_glyphs (it, IT_CONTINUATION);
3358 it->continuation_pixel_width = it->pixel_width;
3359 }
3360 }
3361
3362
3363
3364 it->pixel_width = it->ascent = it->descent = 0;
3365 it->phys_ascent = it->phys_descent = 0;
3366
3367
3368
3369
3370 it->glyph_row = row;
3371 it->area = TEXT_AREA;
3372
3373
3374
3375
3376
3377 if (base_face_id != DEFAULT_FACE_ID)
3378 {
3379
3380 it->first_visible_x = 0;
3381 it->last_visible_x =
3382 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3383 }
3384 else
3385 {
3386
3387
3388
3389
3390
3391
3392 if (hscrolling_current_line_p (w))
3393 {
3394 if (w->min_hscroll > 0)
3395 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3396 else
3397 it->first_visible_x = 0;
3398 }
3399 else
3400 it->first_visible_x =
3401 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3402
3403 body_width = window_box_width (w, TEXT_AREA);
3404 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3405 && body_width != w->old_body_pixel_width)
3406 FRAME_WINDOW_CHANGE (it->f) = true;
3407 it->last_visible_x = it->first_visible_x + body_width;
3408
3409
3410
3411
3412 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3413 {
3414 if (it->line_wrap == TRUNCATE)
3415 it->last_visible_x -= it->truncation_pixel_width;
3416 else
3417 it->last_visible_x -= it->continuation_pixel_width;
3418 }
3419
3420 it->tab_line_p = window_wants_tab_line (w);
3421 it->header_line_p = window_wants_header_line (w);
3422 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3423 it->current_y = body_height + w->vscroll;
3424 }
3425
3426
3427 if (!FRAME_WINDOW_P (it->f)
3428 && !WINDOW_RIGHTMOST_P (it->w))
3429 it->last_visible_x -= 1;
3430
3431 it->last_visible_y = window_text_bottom_y (w);
3432 body_height += it->last_visible_y;
3433 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3434 && body_height != w->old_body_pixel_height)
3435 FRAME_WINDOW_CHANGE (it->f) = true;
3436
3437
3438
3439 if (base_face_id != DEFAULT_FACE_ID)
3440 {
3441 struct face *face;
3442
3443 it->face_id = remapped_base_face_id;
3444
3445
3446
3447 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3448 if (face && face->box != FACE_NO_BOX)
3449 {
3450 int box_thickness = face->box_vertical_line_width;
3451 it->face_box_p = true;
3452 it->start_of_box_run_p = true;
3453
3454
3455 if (box_thickness > 0)
3456 it->last_visible_x -= box_thickness;
3457 }
3458 }
3459
3460
3461
3462 if (charpos >= BUF_BEG (current_buffer))
3463 {
3464 it->stop_charpos = charpos;
3465 it->end_charpos = ZV;
3466 eassert (charpos == BYTE_TO_CHAR (bytepos));
3467 IT_CHARPOS (*it) = charpos;
3468 IT_BYTEPOS (*it) = bytepos;
3469
3470
3471
3472 it->face_id = it->base_face_id;
3473
3474 it->start = it->current;
3475
3476
3477
3478
3479
3480
3481
3482 it->bidi_p =
3483 !redisplay__inhibit_bidi
3484 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3485 && it->multibyte_p;
3486
3487
3488
3489 if (it->bidi_p)
3490 {
3491
3492
3493
3494
3495 if (base_face_id == DEFAULT_FACE_ID
3496 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3497 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3498 {
3499 if (it->line_wrap == TRUNCATE)
3500 it->last_visible_x -= it->truncation_pixel_width;
3501 else
3502 it->last_visible_x -= it->continuation_pixel_width;
3503 }
3504
3505
3506 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3507 Qleft_to_right))
3508 it->paragraph_embedding = L2R;
3509 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3510 Qright_to_left))
3511 it->paragraph_embedding = R2L;
3512 else
3513 it->paragraph_embedding = NEUTRAL_DIR;
3514 bidi_unshelve_cache (NULL, false);
3515 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3516 &it->bidi_it);
3517 }
3518
3519
3520
3521 it->medium_narrowing_begv = 0;
3522
3523
3524 reseat (it, it->current.pos, true);
3525 }
3526
3527 CHECK_IT (it);
3528 }
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616 static int
3617 get_narrowed_width (struct window *w)
3618 {
3619
3620
3621 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3622
3623
3624
3625 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3626 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3627 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3628 return fact * max (1, width);
3629 }
3630
3631 static int
3632 get_narrowed_len (struct window *w)
3633 {
3634 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3635 return get_narrowed_width (w) * max (1, height);
3636 }
3637
3638 static ptrdiff_t
3639 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3640 {
3641 int len = get_narrowed_len (w);
3642 return max ((pos / len - 1) * len, BEGV);
3643 }
3644
3645 static ptrdiff_t
3646 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3647 {
3648 int len = get_narrowed_len (w);
3649 return min ((pos / len + 1) * len, ZV);
3650 }
3651
3652
3653
3654
3655
3656
3657 static ptrdiff_t
3658 get_nearby_bol_pos (ptrdiff_t pos)
3659 {
3660 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3661 int dist;
3662 for (dist = 500; dist <= 500000; dist *= 10)
3663 {
3664 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3665 start = pos - dist < BEGV ? BEGV : pos - dist;
3666 for (cur = start; cur < pos; cur = next)
3667 {
3668 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3669 pos, pos_bytepos,
3670 1, &found, NULL, false);
3671 if (found)
3672 bol = next;
3673 else
3674 break;
3675 }
3676 if (bol >= BEGV || start == BEGV)
3677 break;
3678 else
3679 pos = pos - dist < BEGV ? BEGV : pos - dist;
3680 }
3681 eassert (bol <= init_pos);
3682 return bol;
3683 }
3684
3685 ptrdiff_t
3686 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3687 {
3688 int len = get_narrowed_width (w);
3689 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3690 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3691 }
3692
3693 ptrdiff_t
3694 get_large_narrowing_begv (ptrdiff_t pos)
3695 {
3696 if (long_line_optimizations_region_size <= 0)
3697 return BEGV;
3698 int len = long_line_optimizations_region_size / 2;
3699 int begv = max (pos - len, BEGV);
3700 int limit = long_line_optimizations_bol_search_limit;
3701 while (limit > 0)
3702 {
3703 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3704 return begv;
3705 begv--;
3706 limit--;
3707 }
3708 return begv;
3709 }
3710
3711 ptrdiff_t
3712 get_large_narrowing_zv (ptrdiff_t pos)
3713 {
3714 if (long_line_optimizations_region_size <= 0)
3715 return ZV;
3716 int len = long_line_optimizations_region_size / 2;
3717 return min (pos + len, ZV);
3718 }
3719
3720 static void
3721 unwind_narrowed_begv (Lisp_Object point_min)
3722 {
3723 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3724 }
3725
3726
3727
3728
3729 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3730 do { \
3731 if (IT->medium_narrowing_begv) \
3732 { \
3733 specpdl_ref count = SPECPDL_INDEX (); \
3734 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3735 SET_BUF_BEGV (current_buffer, BV); \
3736 DST = EXPR; \
3737 unbind_to (count, Qnil); \
3738 } \
3739 else \
3740 DST = EXPR; \
3741 } while (0)
3742
3743
3744
3745 void
3746 start_display (struct it *it, struct window *w, struct text_pos pos)
3747 {
3748 struct glyph_row *row;
3749 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3750
3751 row = w->desired_matrix->rows + first_vpos;
3752 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3753 it->first_vpos = first_vpos;
3754
3755
3756
3757 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3758 {
3759 int first_y = it->current_y;
3760
3761
3762
3763 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3764 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3765 if (!start_at_line_beg_p)
3766 {
3767 int new_x;
3768
3769 reseat_at_previous_visible_line_start (it);
3770 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3771
3772 new_x = it->current_x + it->pixel_width;
3773
3774
3775
3776
3777
3778
3779
3780 if (it->current_x > 0
3781 && it->line_wrap != TRUNCATE
3782 && (
3783 new_x > it->last_visible_x
3784
3785
3786 || (new_x == it->last_visible_x
3787 && FRAME_WINDOW_P (it->f)
3788 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3789 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3790 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3791 {
3792 if ((it->current.dpvec_index >= 0
3793 || it->current.overlay_string_index >= 0)
3794
3795
3796
3797
3798
3799 && it->c != '\n')
3800 {
3801 set_iterator_to_next (it, true);
3802 move_it_in_display_line_to (it, -1, -1, 0);
3803 }
3804
3805 it->continuation_lines_width += it->current_x;
3806 }
3807
3808
3809
3810
3811
3812 else if (it->current.dpvec_index >= 0)
3813 it->current.dpvec_index = 0;
3814
3815
3816
3817
3818 it->max_ascent = it->max_descent = 0;
3819 it->max_phys_ascent = it->max_phys_descent = 0;
3820
3821 it->current_y = first_y;
3822 it->vpos = 0;
3823 it->current_x = it->hpos = 0;
3824 }
3825 }
3826 }
3827
3828
3829
3830
3831
3832 static bool
3833 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3834 {
3835 Lisp_Object prop, window;
3836 bool ellipses_p = false;
3837 ptrdiff_t charpos = CHARPOS (pos->pos);
3838
3839
3840
3841
3842
3843 if (pos->dpvec_index >= 0
3844 && pos->overlay_string_index < 0
3845 && CHARPOS (pos->string_pos) < 0
3846 && charpos > BEGV
3847 && (XSETWINDOW (window, w),
3848 prop = Fget_char_property (make_fixnum (charpos),
3849 Qinvisible, window),
3850 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3851 {
3852 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3853 window);
3854 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3855 }
3856
3857 return ellipses_p;
3858 }
3859
3860
3861
3862
3863
3864
3865
3866 static bool
3867 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3868 {
3869 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3870 int i;
3871 bool overlay_strings_with_newlines = false;
3872
3873
3874
3875
3876
3877 if (in_ellipses_for_invisible_text_p (pos, w))
3878 {
3879 --charpos;
3880 bytepos = 0;
3881 }
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3893
3894
3895
3896
3897 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3898 {
3899 const char *s = SSDATA (it->overlay_strings[i]);
3900 const char *e = s + SBYTES (it->overlay_strings[i]);
3901
3902 while (s < e && *s != '\n')
3903 ++s;
3904
3905 if (s < e)
3906 {
3907 overlay_strings_with_newlines = true;
3908 break;
3909 }
3910 }
3911
3912
3913
3914 if (pos->overlay_string_index >= 0)
3915 {
3916 int relative_index;
3917
3918
3919
3920
3921
3922 if (it->method == GET_FROM_IMAGE)
3923 pop_it (it);
3924
3925
3926
3927
3928 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3929 {
3930 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3931 it->current.overlay_string_index = 0;
3932 while (n--)
3933 {
3934 load_overlay_strings (it, 0);
3935 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3936 }
3937 }
3938
3939 it->current.overlay_string_index = pos->overlay_string_index;
3940 relative_index = (it->current.overlay_string_index
3941 % OVERLAY_STRING_CHUNK_SIZE);
3942 it->string = it->overlay_strings[relative_index];
3943 eassert (STRINGP (it->string));
3944 it->current.string_pos = pos->string_pos;
3945 it->method = GET_FROM_STRING;
3946 it->end_charpos = SCHARS (it->string);
3947
3948 if (it->bidi_p)
3949 {
3950 it->bidi_it.string.lstring = it->string;
3951 it->bidi_it.string.s = NULL;
3952 it->bidi_it.string.schars = SCHARS (it->string);
3953 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3954 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3955 it->bidi_it.string.unibyte = !it->multibyte_p;
3956 it->bidi_it.w = it->w;
3957 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3958 FRAME_WINDOW_P (it->f), &it->bidi_it);
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968 if (CHARPOS (pos->string_pos) == 0)
3969 {
3970 get_visually_first_element (it);
3971 if (IT_STRING_CHARPOS (*it) != 0)
3972 do {
3973
3974 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3975 bidi_move_to_visually_next (&it->bidi_it);
3976 } while (it->bidi_it.charpos != 0);
3977 }
3978 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3979 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3980 }
3981 }
3982
3983 if (CHARPOS (pos->string_pos) >= 0)
3984 {
3985
3986
3987
3988 it->current.string_pos = pos->string_pos;
3989 eassert (STRINGP (it->string));
3990 if (it->bidi_p)
3991 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3992 FRAME_WINDOW_P (it->f), &it->bidi_it);
3993 }
3994
3995
3996
3997 if (pos->dpvec_index >= 0)
3998 {
3999 if (it->dpvec == NULL)
4000 get_next_display_element (it);
4001 eassert (it->dpvec && it->current.dpvec_index == 0);
4002 it->current.dpvec_index = pos->dpvec_index;
4003 }
4004
4005 CHECK_IT (it);
4006 return !overlay_strings_with_newlines;
4007 }
4008
4009
4010
4011
4012
4013 static void
4014 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
4015 {
4016 init_from_display_pos (it, w, &row->start);
4017 it->start = row->start;
4018 it->continuation_lines_width = row->continuation_lines_width;
4019 CHECK_IT (it);
4020 }
4021
4022
4023
4024
4025
4026
4027
4028
4029 static bool
4030 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
4031 {
4032 bool success = false;
4033
4034 if (init_from_display_pos (it, w, &row->end))
4035 {
4036 if (row->continued_p)
4037 it->continuation_lines_width
4038 = row->continuation_lines_width + row->pixel_width;
4039 CHECK_IT (it);
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049 if (get_next_display_element (it)
4050 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4051 success = false;
4052 else
4053 success = true;
4054 }
4055
4056 return success;
4057 }
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070 static void
4071 handle_stop (struct it *it)
4072 {
4073 enum prop_handled handled;
4074 bool handle_overlay_change_p;
4075 struct props *p;
4076
4077 it->dpvec = NULL;
4078 it->current.dpvec_index = -1;
4079 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4080 it->ellipsis_p = false;
4081
4082
4083 if (it->selective_display_ellipsis_p)
4084 it->saved_face_id = it->face_id;
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128 do
4129 {
4130 handled = HANDLED_NORMALLY;
4131
4132
4133 for (p = it_props; p->handler; ++p)
4134 {
4135 handled = p->handler (it);
4136
4137 if (handled == HANDLED_RECOMPUTE_PROPS)
4138 break;
4139 else if (handled == HANDLED_RETURN)
4140 {
4141
4142
4143 if (!handle_overlay_change_p
4144 || it->sp > 1
4145
4146
4147
4148
4149
4150
4151 || (it->current.overlay_string_index < 0
4152 && !get_overlay_strings_1 (it, 0, false)))
4153 {
4154 if (it->ellipsis_p)
4155 setup_for_ellipsis (it, 0);
4156
4157
4158
4159
4160
4161 if (STRINGP (it->string) && !SCHARS (it->string))
4162 pop_it (it);
4163 return;
4164 }
4165 else if (STRINGP (it->string) && !SCHARS (it->string))
4166 pop_it (it);
4167 else
4168 {
4169 it->string_from_display_prop_p = false;
4170 it->from_disp_prop_p = false;
4171 handle_overlay_change_p = false;
4172 }
4173 handled = HANDLED_RECOMPUTE_PROPS;
4174 break;
4175 }
4176 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4177 handle_overlay_change_p = false;
4178 }
4179
4180 if (handled != HANDLED_RECOMPUTE_PROPS)
4181 {
4182
4183
4184 if (it->method == GET_FROM_DISPLAY_VECTOR)
4185 handle_overlay_change_p = false;
4186
4187
4188
4189
4190 if (handle_overlay_change_p)
4191 handled = handle_overlay_change (it);
4192 }
4193
4194 if (it->ellipsis_p)
4195 {
4196 setup_for_ellipsis (it, 0);
4197 break;
4198 }
4199 }
4200 while (handled == HANDLED_RECOMPUTE_PROPS);
4201
4202
4203 if (handled == HANDLED_NORMALLY)
4204 compute_stop_pos (it);
4205 }
4206
4207
4208
4209
4210
4211 static void
4212 compute_stop_pos (struct it *it)
4213 {
4214 register INTERVAL iv, next_iv;
4215 Lisp_Object object, limit, position;
4216 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4217
4218 if (STRINGP (it->string))
4219 {
4220
4221
4222 it->stop_charpos = it->end_charpos;
4223 object = it->string;
4224 limit = Qnil;
4225 charpos = IT_STRING_CHARPOS (*it);
4226 bytepos = IT_STRING_BYTEPOS (*it);
4227 }
4228 else
4229 {
4230 ptrdiff_t pos;
4231
4232
4233
4234 if (it->end_charpos > ZV)
4235 it->end_charpos = ZV;
4236 it->stop_charpos = it->end_charpos;
4237
4238
4239
4240
4241
4242 charpos = IT_CHARPOS (*it);
4243 bytepos = IT_BYTEPOS (*it);
4244 pos = next_overlay_change (charpos);
4245 if (pos < it->stop_charpos)
4246 it->stop_charpos = pos;
4247
4248 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4249 && !NILP (Vauto_composition_mode)
4250 && composition_break_at_point
4251 && charpos < PT && PT < it->stop_charpos)
4252 it->stop_charpos = PT;
4253
4254
4255
4256 XSETBUFFER (object, current_buffer);
4257 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4258
4259
4260
4261
4262
4263
4264 if (!composition_break_at_point
4265 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4266 && !NILP (Vauto_composition_mode))
4267 {
4268 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4269 bool found = false;
4270
4271 if (pos > ZV)
4272 pos = ZV;
4273 if (endpos > ZV)
4274 endpos = ZV;
4275 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4276 while (pos < endpos)
4277 {
4278 int ch = fetch_char_advance_no_check (&pos, &bpos);
4279 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4280 {
4281 found = true;
4282 break;
4283 }
4284 }
4285 if (found)
4286 {
4287 pos--;
4288 cmp_limit_pos = pos;
4289 }
4290 else if (it->stop_charpos < endpos)
4291 pos = it->stop_charpos;
4292 else
4293 {
4294
4295 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4296 }
4297 }
4298 limit = make_fixnum (pos);
4299 }
4300
4301
4302
4303 position = make_fixnum (charpos);
4304 iv = validate_interval_range (object, &position, &position, false);
4305 if (iv)
4306 {
4307 Lisp_Object values_here[LAST_PROP_IDX];
4308 struct props *p;
4309
4310
4311 for (p = it_props; p->handler; ++p)
4312 values_here[p->idx] = textget (iv->plist,
4313 builtin_lisp_symbol (p->name));
4314
4315
4316
4317 for (next_iv = next_interval (iv);
4318 (next_iv
4319 && (NILP (limit)
4320 || XFIXNAT (limit) > next_iv->position));
4321 next_iv = next_interval (next_iv))
4322 {
4323 for (p = it_props; p->handler; ++p)
4324 {
4325 Lisp_Object new_value = textget (next_iv->plist,
4326 builtin_lisp_symbol (p->name));
4327 if (!EQ (values_here[p->idx], new_value))
4328 break;
4329 }
4330
4331 if (p->handler)
4332 break;
4333 }
4334
4335 if (next_iv)
4336 {
4337 if (FIXNUMP (limit)
4338 && next_iv->position >= XFIXNAT (limit))
4339
4340 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4341 else
4342
4343 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4344 }
4345 }
4346
4347 if (it->cmp_it.id < 0
4348 && (STRINGP (it->string)
4349 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4350 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4351 {
4352 ptrdiff_t stoppos = it->end_charpos;
4353
4354
4355
4356
4357 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4358 stoppos = -1;
4359 else if (cmp_limit_pos > 0)
4360 stoppos = cmp_limit_pos;
4361
4362
4363
4364 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4365 stoppos, it->string, false);
4366 }
4367
4368 eassert (STRINGP (it->string)
4369 || (it->stop_charpos >= BEGV
4370 && it->stop_charpos >= IT_CHARPOS (*it)));
4371 }
4372
4373
4374
4375
4376 #define MAX_DISP_SCAN 250
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390 ptrdiff_t
4391 compute_display_string_pos (struct text_pos *position,
4392 struct bidi_string_data *string,
4393 struct window *w,
4394 bool frame_window_p, int *disp_prop)
4395 {
4396
4397 Lisp_Object object, object1;
4398 Lisp_Object pos, spec, limpos;
4399 bool string_p = string && (STRINGP (string->lstring) || string->s);
4400 ptrdiff_t eob = string_p ? string->schars : ZV;
4401 ptrdiff_t begb = string_p ? 0 : BEGV;
4402 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4403 ptrdiff_t lim =
4404 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4405 struct text_pos tpos;
4406 int rv = 0;
4407
4408 if (string && STRINGP (string->lstring))
4409 object1 = object = string->lstring;
4410 else if (w && !string_p)
4411 {
4412 XSETWINDOW (object, w);
4413 object1 = Qnil;
4414 }
4415 else
4416 object1 = object = Qnil;
4417
4418 *disp_prop = 1;
4419
4420 if (charpos >= eob
4421
4422
4423 || string->from_disp_str
4424
4425 || (string->s && !STRINGP (object)))
4426 {
4427 *disp_prop = 0;
4428 return eob;
4429 }
4430
4431
4432
4433 pos = make_fixnum (charpos);
4434 if (STRINGP (object))
4435 bufpos = string->bufpos;
4436 else
4437 bufpos = charpos;
4438 tpos = *position;
4439 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4440 && (charpos <= begb
4441 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4442 object),
4443 spec))
4444 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4445 frame_window_p)))
4446 {
4447 if (rv == 2)
4448 *disp_prop = 2;
4449 return charpos;
4450 }
4451
4452
4453
4454 limpos = make_fixnum (lim);
4455 do {
4456 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4457 CHARPOS (tpos) = XFIXNAT (pos);
4458 if (CHARPOS (tpos) >= lim)
4459 {
4460 *disp_prop = 0;
4461 break;
4462 }
4463 if (STRINGP (object))
4464 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4465 else
4466 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4467 spec = Fget_char_property (pos, Qdisplay, object);
4468 if (!STRINGP (object))
4469 bufpos = CHARPOS (tpos);
4470 } while (NILP (spec)
4471 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4472 bufpos, frame_window_p)));
4473 if (rv == 2)
4474 *disp_prop = 2;
4475
4476 return CHARPOS (tpos);
4477 }
4478
4479
4480
4481
4482
4483
4484 ptrdiff_t
4485 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4486 {
4487
4488 Lisp_Object object =
4489 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4490 Lisp_Object pos = make_fixnum (charpos);
4491 ptrdiff_t eob =
4492 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4493
4494 if (charpos >= eob || (string->s && !STRINGP (object)))
4495 return eob;
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4512 return -1;
4513
4514
4515
4516 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4517
4518 return XFIXNAT (pos);
4519 }
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531 static enum prop_handled
4532 handle_fontified_prop (struct it *it)
4533 {
4534 Lisp_Object prop, pos;
4535 enum prop_handled handled = HANDLED_NORMALLY;
4536
4537 if (!NILP (Vmemory_full))
4538 return handled;
4539
4540
4541
4542
4543
4544 if (!STRINGP (it->string)
4545 && it->s == NULL
4546 && !NILP (Vfontification_functions)
4547 && !(input_was_pending && redisplay_skip_fontification_on_input)
4548 && !NILP (Vrun_hooks)
4549 && (pos = make_fixnum (IT_CHARPOS (*it)),
4550 prop = Fget_char_property (pos, Qfontified, Qnil),
4551
4552
4553 NILP (prop) && IT_CHARPOS (*it) < Z))
4554 {
4555 specpdl_ref count = SPECPDL_INDEX ();
4556 Lisp_Object val;
4557 struct buffer *obuf = current_buffer;
4558 ptrdiff_t begv = BEGV, zv = ZV;
4559 bool old_clip_changed = current_buffer->clip_changed;
4560 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4561
4562 val = Vfontification_functions;
4563 specbind (Qfontification_functions, Qnil);
4564
4565 eassert (it->end_charpos == ZV);
4566
4567 if (current_buffer->long_line_optimizations_p
4568 && long_line_optimizations_region_size > 0)
4569 {
4570 ptrdiff_t begv = it->large_narrowing_begv;
4571 ptrdiff_t zv = it->large_narrowing_zv;
4572 ptrdiff_t charpos = IT_CHARPOS (*it);
4573 if (charpos < begv || charpos > zv)
4574 {
4575 begv = get_large_narrowing_begv (charpos);
4576 zv = get_large_narrowing_zv (charpos);
4577 }
4578 if (begv != BEG || zv != Z)
4579 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4580 Qlong_line_optimizations_in_fontification_functions);
4581 }
4582
4583
4584
4585 it->f->inhibit_clear_image_cache = true;
4586
4587 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4588 safe_call1 (val, pos);
4589 else
4590 {
4591 Lisp_Object fns, fn;
4592
4593 fns = Qnil;
4594
4595 for (; CONSP (val); val = XCDR (val))
4596 {
4597 fn = XCAR (val);
4598
4599 if (EQ (fn, Qt))
4600 {
4601
4602
4603
4604
4605
4606 for (fns = Fdefault_value (Qfontification_functions);
4607 CONSP (fns);
4608 fns = XCDR (fns))
4609 {
4610 fn = XCAR (fns);
4611 if (!EQ (fn, Qt))
4612 safe_call1 (fn, pos);
4613 }
4614 }
4615 else
4616 safe_call1 (fn, pos);
4617 }
4618 }
4619
4620 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4621 unbind_to (count, Qnil);
4622
4623
4624
4625
4626
4627
4628
4629
4630 if (obuf == current_buffer)
4631 {
4632 if (begv == BEGV && zv == ZV)
4633 current_buffer->clip_changed = old_clip_changed;
4634 }
4635
4636
4637 else if (BUFFER_LIVE_P (obuf))
4638 set_buffer_internal_1 (obuf);
4639
4640
4641
4642
4643
4644
4645 it->end_charpos = ZV;
4646
4647
4648
4649
4650 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4651 handled = HANDLED_RECOMPUTE_PROPS;
4652 }
4653
4654 return handled;
4655 }
4656
4657
4658
4659
4660
4661
4662
4663 static int
4664 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4665 {
4666 ptrdiff_t next_stop;
4667
4668 if (!STRINGP (it->string))
4669 {
4670 return face_at_buffer_position (it->w,
4671 IT_CHARPOS (*it),
4672 &next_stop,
4673 (IT_CHARPOS (*it)
4674 + TEXT_PROP_DISTANCE_LIMIT),
4675 false, it->base_face_id,
4676 attr_filter);
4677 }
4678 else
4679 {
4680 int base_face_id;
4681 ptrdiff_t bufpos;
4682 int i;
4683 Lisp_Object from_overlay
4684 = (it->current.overlay_string_index >= 0
4685 ? it->string_overlays[it->current.overlay_string_index
4686 % OVERLAY_STRING_CHUNK_SIZE]
4687 : Qnil);
4688
4689
4690
4691
4692
4693
4694
4695 if (! NILP (from_overlay))
4696 for (i = it->sp - 1; i >= 0; i--)
4697 {
4698 if (it->stack[i].current.overlay_string_index >= 0)
4699 from_overlay
4700 = it->string_overlays[it->stack[i].current.overlay_string_index
4701 % OVERLAY_STRING_CHUNK_SIZE];
4702 else if (! NILP (it->stack[i].from_overlay))
4703 from_overlay = it->stack[i].from_overlay;
4704
4705 if (!NILP (from_overlay))
4706 break;
4707 }
4708
4709 if (! NILP (from_overlay))
4710 {
4711 bufpos = IT_CHARPOS (*it);
4712
4713
4714 base_face_id
4715 = face_for_overlay_string (it->w,
4716 IT_CHARPOS (*it),
4717 &next_stop,
4718 (IT_CHARPOS (*it)
4719 + TEXT_PROP_DISTANCE_LIMIT),
4720 false,
4721 from_overlay, attr_filter);
4722 }
4723 else
4724 {
4725 bufpos = 0;
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743 base_face_id = it->string_from_prefix_prop_p
4744 ? (!NILP (Vface_remapping_alist)
4745 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4746 : DEFAULT_FACE_ID)
4747 : underlying_face_id (it);
4748 }
4749
4750 return face_at_string_position (it->w,
4751 it->string,
4752 IT_STRING_CHARPOS (*it),
4753 bufpos,
4754 &next_stop,
4755 base_face_id, false,
4756 attr_filter);
4757 }
4758 }
4759
4760
4761
4762
4763 static enum prop_handled
4764 handle_face_prop (struct it *it)
4765 {
4766 specpdl_ref count = SPECPDL_INDEX ();
4767
4768
4769
4770 specbind (Qinhibit_quit, Qt);
4771 const int new_face_id = face_at_pos (it, 0);
4772 unbind_to (count, Qnil);
4773
4774
4775
4776
4777
4778
4779
4780
4781 if (new_face_id != it->face_id)
4782 {
4783 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4784
4785
4786
4787 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4788
4789
4790
4791
4792 if (!STRINGP (it->string)
4793 && !old_face
4794 && IT_CHARPOS (*it) > BEG)
4795 {
4796 const int prev_face_id = face_before_it_pos (it);
4797
4798 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4799 }
4800
4801
4802
4803
4804 it->face_id = new_face_id;
4805
4806
4807 if (!(it->start_of_box_run_p && old_face && old_face->box))
4808 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4809 && (old_face == NULL || !old_face->box));
4810 it->face_box_p = new_face->box != FACE_NO_BOX;
4811 }
4812
4813 return HANDLED_NORMALLY;
4814 }
4815
4816
4817
4818
4819
4820
4821
4822 static int
4823 underlying_face_id (const struct it *it)
4824 {
4825 int face_id = it->base_face_id, i;
4826
4827 eassert (STRINGP (it->string));
4828
4829 for (i = it->sp - 1; i >= 0; --i)
4830 if (NILP (it->stack[i].string))
4831 face_id = it->stack[i].face_id;
4832
4833 return face_id;
4834 }
4835
4836
4837
4838
4839
4840
4841
4842 static int
4843 face_before_or_after_it_pos (struct it *it, bool before_p)
4844 {
4845 int face_id, limit;
4846 ptrdiff_t next_check_charpos;
4847 struct it it_copy;
4848 void *it_copy_data = NULL;
4849
4850 eassert (it->s == NULL);
4851
4852 if (STRINGP (it->string))
4853 {
4854 ptrdiff_t bufpos, charpos;
4855 int base_face_id;
4856
4857
4858
4859
4860
4861 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4862 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4863 || it->current_x <= it->first_visible_x)
4864 return it->face_id;
4865
4866 if (!it->bidi_p)
4867 {
4868
4869
4870
4871 if (before_p)
4872 charpos = IT_STRING_CHARPOS (*it) - 1;
4873 else if (it->what == IT_COMPOSITION)
4874
4875
4876 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4877 else
4878 charpos = IT_STRING_CHARPOS (*it) + 1;
4879 }
4880 else
4881 {
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892 SAVE_IT (it_copy, *it, it_copy_data);
4893 IT_STRING_CHARPOS (it_copy) = 0;
4894 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4895 it_copy.bidi_it.scan_dir = 0;
4896
4897 do
4898 {
4899 charpos = it_copy.bidi_it.charpos;
4900 if (charpos >= SCHARS (it->string))
4901 break;
4902 bidi_move_to_visually_next (&it_copy.bidi_it);
4903 }
4904 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4905
4906 if (!before_p)
4907 {
4908
4909
4910
4911 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4912
4913
4914
4915 if (it_copy.bidi_it.first_elt)
4916 n++;
4917 while (n--)
4918 bidi_move_to_visually_next (&it_copy.bidi_it);
4919
4920 charpos = it_copy.bidi_it.charpos;
4921 }
4922
4923 RESTORE_IT (it, it, it_copy_data);
4924 }
4925 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4926
4927 if (it->current.overlay_string_index >= 0)
4928 bufpos = IT_CHARPOS (*it);
4929 else
4930 bufpos = 0;
4931
4932 base_face_id = underlying_face_id (it);
4933
4934
4935 face_id = face_at_string_position (it->w, it->string, charpos,
4936 bufpos, &next_check_charpos,
4937 base_face_id, false, 0);
4938
4939
4940
4941
4942 if (STRING_MULTIBYTE (it->string))
4943 {
4944 struct text_pos pos1 = string_pos (charpos, it->string);
4945 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4946 struct face *face = FACE_FROM_ID (it->f, face_id);
4947 int len, c = check_char_and_length (p, &len);
4948 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4949 }
4950 }
4951 else
4952 {
4953 struct text_pos pos;
4954
4955 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4956 || (IT_CHARPOS (*it) <= BEGV && before_p))
4957 return it->face_id;
4958
4959 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4960 pos = it->current.pos;
4961
4962 if (!it->bidi_p)
4963 {
4964 if (before_p)
4965 DEC_TEXT_POS (pos, it->multibyte_p);
4966 else
4967 {
4968 if (it->what == IT_COMPOSITION)
4969 {
4970
4971
4972 pos.charpos += it->cmp_it.nchars;
4973 pos.bytepos += it->len;
4974 }
4975 else
4976 INC_TEXT_POS (pos, it->multibyte_p);
4977 }
4978 }
4979 else
4980 {
4981 if (before_p)
4982 {
4983 int current_x;
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994 if (it->current_x <= it->first_visible_x)
4995 return it->face_id;
4996 SAVE_IT (it_copy, *it, it_copy_data);
4997
4998
4999
5000
5001
5002 current_x = it_copy.current_x;
5003 move_it_vertically_backward (&it_copy, 0);
5004 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
5005 pos = it_copy.current.pos;
5006 RESTORE_IT (it, it, it_copy_data);
5007 }
5008 else
5009 {
5010
5011
5012
5013 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
5014
5015 it_copy = *it;
5016
5017
5018
5019 if (it->bidi_it.first_elt)
5020 n++;
5021 while (n--)
5022 bidi_move_to_visually_next (&it_copy.bidi_it);
5023
5024 SET_TEXT_POS (pos,
5025 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
5026 }
5027 }
5028 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
5029
5030
5031 face_id = face_at_buffer_position (it->w,
5032 CHARPOS (pos),
5033 &next_check_charpos,
5034 limit, false, -1, 0);
5035
5036
5037
5038
5039 if (it->multibyte_p)
5040 {
5041 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5042 struct face *face = FACE_FROM_ID (it->f, face_id);
5043 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5044 }
5045 }
5046
5047 return face_id;
5048 }
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059 static enum prop_handled
5060 handle_invisible_prop (struct it *it)
5061 {
5062 enum prop_handled handled = HANDLED_NORMALLY;
5063 int invis;
5064 Lisp_Object prop;
5065
5066 if (STRINGP (it->string))
5067 {
5068 Lisp_Object end_charpos, limit;
5069
5070
5071
5072
5073 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5074 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5075 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5076
5077 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5078 {
5079
5080
5081 bool display_ellipsis_p = (invis == 2);
5082 ptrdiff_t len, endpos;
5083
5084 handled = HANDLED_RECOMPUTE_PROPS;
5085
5086
5087
5088 endpos = len = SCHARS (it->string);
5089 XSETINT (limit, len);
5090 do
5091 {
5092 end_charpos
5093 = Fnext_single_property_change (end_charpos, Qinvisible,
5094 it->string, limit);
5095
5096
5097 eassert (FIXNUMP (end_charpos));
5098 if (FIXNUMP (end_charpos))
5099 {
5100 endpos = XFIXNAT (end_charpos);
5101 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5102 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5103 if (invis == 2)
5104 display_ellipsis_p = true;
5105 }
5106 else
5107 endpos = len;
5108 }
5109 while (invis != 0 && endpos < len);
5110
5111 if (display_ellipsis_p)
5112 it->ellipsis_p = true;
5113
5114 if (endpos < len)
5115 {
5116
5117 struct text_pos old;
5118 ptrdiff_t oldpos;
5119
5120 old = it->current.string_pos;
5121 oldpos = CHARPOS (old);
5122 if (it->bidi_p)
5123 {
5124 if (it->bidi_it.first_elt
5125 && it->bidi_it.charpos < SCHARS (it->string))
5126 bidi_paragraph_init (it->paragraph_embedding,
5127 &it->bidi_it, true);
5128
5129 do
5130 {
5131 bidi_move_to_visually_next (&it->bidi_it);
5132 }
5133 while (oldpos <= it->bidi_it.charpos
5134 && it->bidi_it.charpos < endpos
5135 && it->bidi_it.charpos < it->bidi_it.string.schars);
5136
5137 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5138 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5139 if (IT_CHARPOS (*it) >= endpos)
5140 it->prev_stop = endpos;
5141 }
5142 else
5143 {
5144 IT_STRING_CHARPOS (*it) = endpos;
5145 compute_string_pos (&it->current.string_pos, old, it->string);
5146 }
5147 }
5148 else
5149 {
5150
5151
5152
5153 if (it->current.overlay_string_index >= 0
5154 && !display_ellipsis_p)
5155 {
5156 next_overlay_string (it);
5157
5158
5159 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5160 }
5161 else
5162 {
5163 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5164 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5165 }
5166 }
5167 }
5168 }
5169 else
5170 {
5171 ptrdiff_t newpos, next_stop, start_charpos, tem;
5172 Lisp_Object pos, overlay;
5173
5174
5175 tem = start_charpos = IT_CHARPOS (*it);
5176 pos = make_fixnum (tem);
5177 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5178 &overlay);
5179 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5180
5181
5182 if (invis != 0 && start_charpos < it->end_charpos)
5183 {
5184
5185
5186 bool display_ellipsis_p = invis == 2;
5187
5188 handled = HANDLED_RECOMPUTE_PROPS;
5189
5190
5191
5192 do
5193 {
5194
5195
5196
5197
5198
5199 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5200
5201
5202
5203
5204 if (newpos == tem || newpos >= ZV)
5205 invis = 0;
5206 else
5207 {
5208
5209
5210
5211
5212
5213
5214 pos = make_fixnum (newpos);
5215 prop = Fget_char_property (pos, Qinvisible, it->window);
5216 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5217 }
5218
5219
5220
5221 if (invis != 0)
5222 tem = next_stop;
5223
5224
5225
5226 if (invis == 2)
5227 display_ellipsis_p = true;
5228 }
5229 while (invis != 0);
5230
5231
5232 if (it->bidi_p)
5233 {
5234 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5235 bool on_newline
5236 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5237 bool after_newline
5238 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5239
5240
5241
5242
5243
5244
5245
5246
5247 if (on_newline || after_newline)
5248 {
5249 struct text_pos tpos;
5250 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5251
5252 SET_TEXT_POS (tpos, newpos, bpos);
5253 reseat_1 (it, tpos, false);
5254
5255
5256
5257
5258
5259 if (on_newline)
5260 {
5261 it->bidi_it.first_elt = false;
5262 it->bidi_it.paragraph_dir = pdir;
5263 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5264 it->bidi_it.nchars = 1;
5265 it->bidi_it.ch_len = 1;
5266 }
5267 }
5268 else
5269 {
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5281 {
5282
5283
5284
5285
5286
5287
5288
5289 bidi_paragraph_init (it->paragraph_embedding,
5290 &it->bidi_it, true);
5291 }
5292 do
5293 {
5294 bidi_move_to_visually_next (&it->bidi_it);
5295 }
5296 while (it->stop_charpos <= it->bidi_it.charpos
5297 && it->bidi_it.charpos < newpos);
5298 IT_CHARPOS (*it) = it->bidi_it.charpos;
5299 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5300
5301
5302
5303
5304 if (IT_CHARPOS (*it) >= newpos)
5305 it->prev_stop = newpos;
5306 }
5307 }
5308 else
5309 {
5310 IT_CHARPOS (*it) = newpos;
5311 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5312 }
5313
5314 if (display_ellipsis_p)
5315 {
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328 if (!STRINGP (it->object))
5329 {
5330 it->position.charpos = newpos - 1;
5331 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5332 }
5333 }
5334
5335
5336
5337
5338
5339
5340
5341 if (NILP (overlay)
5342 && get_overlay_strings (it, it->stop_charpos))
5343 {
5344 handled = HANDLED_RECOMPUTE_PROPS;
5345 if (it->sp > 0)
5346 {
5347 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360 it->stack[it->sp - 1].stop_charpos
5361 = CHARPOS (it->stack[it->sp - 1].current.pos);
5362 }
5363 }
5364 else if (display_ellipsis_p)
5365 {
5366 it->ellipsis_p = true;
5367
5368
5369
5370 handled = HANDLED_RETURN;
5371 }
5372 }
5373 }
5374
5375 return handled;
5376 }
5377
5378
5379
5380
5381
5382 static void
5383 setup_for_ellipsis (struct it *it, int len)
5384 {
5385
5386
5387 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5388 {
5389 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5390 it->dpvec = v->contents;
5391 it->dpend = v->contents + v->header.size;
5392 }
5393 else
5394 {
5395
5396 it->dpvec = default_invis_vector;
5397 it->dpend = default_invis_vector + 3;
5398 }
5399
5400 it->dpvec_char_len = len;
5401 it->current.dpvec_index = 0;
5402 it->dpvec_face_id = -1;
5403
5404
5405
5406
5407
5408
5409
5410
5411 if (it->saved_face_id >= 0)
5412 it->face_id = it->saved_face_id;
5413
5414
5415
5416 if (it->method == GET_FROM_BUFFER)
5417 it->ignore_overlay_strings_at_pos_p = false;
5418
5419 it->method = GET_FROM_DISPLAY_VECTOR;
5420 it->ellipsis_p = true;
5421 }
5422
5423
5424 static Lisp_Object
5425 find_display_property (Lisp_Object disp, Lisp_Object prop)
5426 {
5427 if (NILP (disp))
5428 return Qnil;
5429
5430 if (VECTORP (disp))
5431 {
5432 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5433 {
5434 Lisp_Object elem = AREF (disp, i);
5435 if (CONSP (elem)
5436 && CONSP (XCDR (elem))
5437 && EQ (XCAR (elem), prop))
5438 return XCAR (XCDR (elem));
5439 }
5440 return Qnil;
5441 }
5442
5443 else if (CONSP (disp)
5444 && CONSP (XCAR (disp)))
5445 {
5446 while (!NILP (disp))
5447 {
5448 Lisp_Object elem = XCAR (disp);
5449 if (CONSP (elem)
5450 && CONSP (XCDR (elem))
5451 && EQ (XCAR (elem), prop))
5452 return XCAR (XCDR (elem));
5453
5454
5455
5456 if (CONSP (XCDR (disp)))
5457 disp = XCDR (disp);
5458 else
5459 disp = Qnil;
5460 }
5461 return Qnil;
5462 }
5463
5464 else if (CONSP (disp)
5465 && CONSP (XCDR (disp))
5466 && EQ (XCAR (disp), prop))
5467 return XCAR (XCDR (disp));
5468 else
5469 return Qnil;
5470 }
5471
5472 static Lisp_Object
5473 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5474 {
5475 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5476 Qdisplay, object),
5477 prop);
5478 }
5479
5480 static void
5481 display_min_width (struct it *it, ptrdiff_t bufpos,
5482 Lisp_Object object, Lisp_Object width_spec)
5483 {
5484
5485
5486 if (!NILP (it->min_width_property)
5487 && !EQ (width_spec, it->min_width_property))
5488 {
5489 if (!it->glyph_row)
5490 return;
5491
5492
5493
5494
5495
5496 if ((bufpos == 0
5497 && !EQ (it->min_width_property,
5498 get_display_property (0, Qmin_width, object)))
5499
5500
5501 || (bufpos > BEGV
5502 && EQ (it->min_width_property,
5503 get_display_property (bufpos - 1, Qmin_width, object))))
5504 {
5505 Lisp_Object w = Qnil;
5506 double width;
5507 #ifdef HAVE_WINDOW_SYSTEM
5508 if (FRAME_WINDOW_P (it->f))
5509 {
5510 struct font *font = NULL;
5511 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5512 font = face->font ? face->font : FRAME_FONT (it->f);
5513 calc_pixel_width_or_height (&width, it,
5514 XCAR (it->min_width_property),
5515 font, true, NULL);
5516 width -= it->current_x - it->min_width_start;
5517 w = list1 (make_int (width));
5518 }
5519 else
5520 #endif
5521 {
5522 calc_pixel_width_or_height (&width, it,
5523 XCAR (it->min_width_property),
5524 NULL, true, NULL);
5525 width -= (it->current_x - it->min_width_start) /
5526 FRAME_COLUMN_WIDTH (it->f);
5527 w = make_int (width);
5528 }
5529
5530
5531 it->object = list3 (Qspace, QCwidth, w);
5532 produce_stretch_glyph (it);
5533 if (it->area == TEXT_AREA)
5534 it->current_x += it->pixel_width;
5535 it->min_width_property = Qnil;
5536 }
5537 }
5538
5539
5540
5541
5542 if (CONSP (width_spec))
5543 {
5544 if (bufpos == BEGV
5545
5546 || (bufpos == 0
5547 && !EQ (it->min_width_property,
5548 get_display_property (0, Qmin_width, object)))
5549
5550 || (bufpos > BEGV
5551 && !EQ (width_spec,
5552 get_display_property (bufpos - 1, Qmin_width, object))))
5553 {
5554 it->min_width_property = width_spec;
5555 it->min_width_start = it->current_x;
5556 }
5557 }
5558 }
5559
5560 DEFUN ("get-display-property", Fget_display_property,
5561 Sget_display_property, 2, 4, 0,
5562 doc:
5563
5564
5565
5566
5567 )
5568 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5569 Lisp_Object properties)
5570 {
5571 if (NILP (properties))
5572 properties = Fget_text_property (position, Qdisplay, object);
5573 else
5574 CHECK_LIST (properties);
5575
5576 return find_display_property (properties, prop);
5577 }
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591 static enum prop_handled
5592 handle_display_prop (struct it *it)
5593 {
5594 Lisp_Object propval, object, overlay;
5595 struct text_pos *position;
5596 ptrdiff_t bufpos;
5597
5598 int display_replaced = 0;
5599
5600 if (STRINGP (it->string))
5601 {
5602 object = it->string;
5603 position = &it->current.string_pos;
5604 bufpos = CHARPOS (it->current.pos);
5605 }
5606 else
5607 {
5608 XSETWINDOW (object, it->w);
5609 position = &it->current.pos;
5610 bufpos = CHARPOS (*position);
5611 }
5612
5613
5614 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5615 it->space_width = Qnil;
5616 it->font_height = Qnil;
5617 it->voffset = 0;
5618
5619
5620
5621
5622 if (!it->string_from_display_prop_p)
5623 it->area = TEXT_AREA;
5624
5625 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5626 Qdisplay, object, &overlay);
5627
5628
5629 if (!STRINGP (it->string))
5630 object = it->w->contents;
5631
5632
5633 if (!NILP (it->min_width_property)
5634 && NILP (find_display_property (propval, Qmin_width)))
5635 display_min_width (it, bufpos, object, Qnil);
5636
5637 if (NILP (propval))
5638 return HANDLED_NORMALLY;
5639
5640
5641
5642 display_replaced = handle_display_spec (it, propval, object, overlay,
5643 position, bufpos,
5644 FRAME_WINDOW_P (it->f));
5645 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5646 }
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664 static int
5665 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5666 Lisp_Object overlay, struct text_pos *position,
5667 ptrdiff_t bufpos, bool frame_window_p)
5668 {
5669 int replacing = 0;
5670 bool enable_eval = true;
5671
5672
5673 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5674 {
5675 enable_eval = false;
5676 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5677 }
5678
5679 if (CONSP (spec)
5680
5681 && !EQ (XCAR (spec), Qimage)
5682 #ifdef HAVE_XWIDGETS
5683 && !EQ (XCAR (spec), Qxwidget)
5684 #endif
5685 && !EQ (XCAR (spec), Qspace)
5686 && !EQ (XCAR (spec), Qwhen)
5687 && !EQ (XCAR (spec), Qslice)
5688 && !EQ (XCAR (spec), Qspace_width)
5689 && !EQ (XCAR (spec), Qheight)
5690 && !EQ (XCAR (spec), Qraise)
5691
5692 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5693 && !EQ (XCAR (spec), Qleft_fringe)
5694 && !EQ (XCAR (spec), Qright_fringe)
5695 && !EQ (XCAR (spec), Qmin_width)
5696 && !NILP (XCAR (spec)))
5697 {
5698 for (; CONSP (spec); spec = XCDR (spec))
5699 {
5700 int rv = handle_single_display_spec (it, XCAR (spec), object,
5701 overlay, position, bufpos,
5702 replacing, frame_window_p,
5703 enable_eval);
5704 if (rv != 0)
5705 {
5706 replacing = rv;
5707
5708
5709 if (!it || STRINGP (object))
5710 break;
5711 }
5712 }
5713 }
5714 else if (VECTORP (spec))
5715 {
5716 ptrdiff_t i;
5717 for (i = 0; i < ASIZE (spec); ++i)
5718 {
5719 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5720 overlay, position, bufpos,
5721 replacing, frame_window_p,
5722 enable_eval);
5723 if (rv != 0)
5724 {
5725 replacing = rv;
5726
5727
5728 if (!it || STRINGP (object))
5729 break;
5730 }
5731 }
5732 }
5733 else
5734 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5735 bufpos, 0, frame_window_p,
5736 enable_eval);
5737 return replacing;
5738 }
5739
5740
5741
5742
5743 static struct text_pos
5744 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5745 {
5746 Lisp_Object end;
5747 struct text_pos end_pos;
5748
5749 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5750 Qdisplay, object, Qnil);
5751 CHARPOS (end_pos) = XFIXNAT (end);
5752 if (STRINGP (object))
5753 compute_string_pos (&end_pos, start_pos, it->string);
5754 else
5755 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5756
5757 return end_pos;
5758 }
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786 static int
5787 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5788 Lisp_Object overlay, struct text_pos *position,
5789 ptrdiff_t bufpos, int display_replaced,
5790 bool frame_window_p, bool enable_eval_p)
5791 {
5792 Lisp_Object form;
5793 Lisp_Object location, value;
5794 struct text_pos start_pos = *position;
5795 void *itdata = NULL;
5796
5797
5798
5799 form = Qt;
5800 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5801 {
5802 spec = XCDR (spec);
5803 if (!CONSP (spec))
5804 return 0;
5805 form = XCAR (spec);
5806 spec = XCDR (spec);
5807 }
5808
5809 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5810 form = Qnil;
5811 if (!NILP (form) && !EQ (form, Qt))
5812 {
5813 specpdl_ref count = SPECPDL_INDEX ();
5814
5815
5816
5817
5818
5819
5820 if (NILP (object))
5821 XSETBUFFER (object, current_buffer);
5822 specbind (Qobject, object);
5823 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5824 specbind (Qbuffer_position, make_fixnum (bufpos));
5825
5826
5827 itdata = bidi_shelve_cache ();
5828 form = safe_eval (form);
5829 bidi_unshelve_cache (itdata, false);
5830 form = unbind_to (count, form);
5831 }
5832
5833 if (NILP (form))
5834 return 0;
5835
5836
5837 if (CONSP (spec)
5838 && EQ (XCAR (spec), Qheight)
5839 && CONSP (XCDR (spec)))
5840 {
5841 if (it)
5842 {
5843 if (!FRAME_WINDOW_P (it->f))
5844 return 0;
5845
5846 it->font_height = XCAR (XCDR (spec));
5847 if (!NILP (it->font_height))
5848 {
5849 int new_height = -1;
5850
5851 if (CONSP (it->font_height)
5852 && (EQ (XCAR (it->font_height), Qplus)
5853 || EQ (XCAR (it->font_height), Qminus))
5854 && CONSP (XCDR (it->font_height))
5855 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5856 {
5857
5858 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5859 if (EQ (XCAR (it->font_height), Qplus))
5860 steps = - steps;
5861 it->face_id = smaller_face (it->f, it->face_id, steps);
5862 }
5863 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5864 {
5865
5866
5867 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5868 Lisp_Object height;
5869 itdata = bidi_shelve_cache ();
5870 height = safe_call1 (it->font_height,
5871 face->lface[LFACE_HEIGHT_INDEX]);
5872 bidi_unshelve_cache (itdata, false);
5873 if (NUMBERP (height))
5874 new_height = XFLOATINT (height);
5875 }
5876 else if (NUMBERP (it->font_height))
5877 {
5878
5879 struct face *f;
5880
5881 f = FACE_FROM_ID (it->f,
5882 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5883 new_height = (XFLOATINT (it->font_height)
5884 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5885 }
5886 else if (enable_eval_p)
5887 {
5888
5889
5890 specpdl_ref count = SPECPDL_INDEX ();
5891 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5892
5893 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5894 itdata = bidi_shelve_cache ();
5895 value = safe_eval (it->font_height);
5896 bidi_unshelve_cache (itdata, false);
5897 value = unbind_to (count, value);
5898
5899 if (NUMBERP (value))
5900 new_height = XFLOATINT (value);
5901 }
5902
5903 if (new_height > 0)
5904 it->face_id = face_with_height (it->f, it->face_id, new_height);
5905 }
5906 }
5907
5908 return 0;
5909 }
5910
5911
5912 if (CONSP (spec)
5913 && EQ (XCAR (spec), Qspace_width)
5914 && CONSP (XCDR (spec)))
5915 {
5916 if (it)
5917 {
5918 if (!FRAME_WINDOW_P (it->f))
5919 return 0;
5920
5921 value = XCAR (XCDR (spec));
5922 if (NUMBERP (value) && XFLOATINT (value) > 0)
5923 it->space_width = value;
5924 }
5925
5926 return 0;
5927 }
5928
5929
5930 if (CONSP (spec)
5931 && EQ (XCAR (spec), Qmin_width)
5932 && CONSP (XCDR (spec))
5933 && CONSP (XCAR (XCDR (spec))))
5934 {
5935 if (it)
5936 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5937 return 0;
5938 }
5939
5940
5941 if (CONSP (spec)
5942 && EQ (XCAR (spec), Qslice))
5943 {
5944 Lisp_Object tem;
5945
5946 if (it)
5947 {
5948 if (!FRAME_WINDOW_P (it->f))
5949 return 0;
5950
5951 if (tem = XCDR (spec), CONSP (tem))
5952 {
5953 it->slice.x = XCAR (tem);
5954 if (tem = XCDR (tem), CONSP (tem))
5955 {
5956 it->slice.y = XCAR (tem);
5957 if (tem = XCDR (tem), CONSP (tem))
5958 {
5959 it->slice.width = XCAR (tem);
5960 if (tem = XCDR (tem), CONSP (tem))
5961 it->slice.height = XCAR (tem);
5962 }
5963 }
5964 }
5965 }
5966
5967 return 0;
5968 }
5969
5970
5971 if (CONSP (spec)
5972 && EQ (XCAR (spec), Qraise)
5973 && CONSP (XCDR (spec)))
5974 {
5975 if (it)
5976 {
5977 if (!FRAME_WINDOW_P (it->f))
5978 return 0;
5979
5980 #ifdef HAVE_WINDOW_SYSTEM
5981 value = XCAR (XCDR (spec));
5982 if (NUMBERP (value))
5983 {
5984 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5985 it->voffset = - (XFLOATINT (value)
5986 * (normal_char_height (face->font, -1)));
5987 }
5988 #endif
5989 }
5990
5991 return 0;
5992 }
5993
5994
5995
5996 if (it && it->string_from_display_prop_p)
5997 return 0;
5998
5999
6000
6001 if (it)
6002 {
6003 start_pos = *position;
6004 *position = display_prop_end (it, object, start_pos);
6005
6006
6007
6008
6009
6010
6011
6012 if (!NILP (overlay))
6013 {
6014 ptrdiff_t ovendpos = OVERLAY_END (overlay);
6015
6016
6017
6018
6019
6020
6021
6022 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
6023
6024 if (ovendpos > CHARPOS (*position))
6025 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
6026 }
6027 }
6028 value = Qnil;
6029
6030
6031
6032 if (it)
6033 it->stop_charpos = position->charpos;
6034
6035
6036
6037 if (CONSP (spec)
6038 && (EQ (XCAR (spec), Qleft_fringe)
6039 || EQ (XCAR (spec), Qright_fringe))
6040 && CONSP (XCDR (spec)))
6041 {
6042 if (it)
6043 {
6044 if (!FRAME_WINDOW_P (it->f))
6045
6046
6047 {
6048
6049
6050
6051
6052 if (it->bidi_p)
6053 {
6054 it->position = *position;
6055 iterate_out_of_display_property (it);
6056 *position = it->position;
6057 }
6058 return 1;
6059 }
6060 }
6061 else if (!frame_window_p)
6062 return 1;
6063
6064 #ifdef HAVE_WINDOW_SYSTEM
6065 value = XCAR (XCDR (spec));
6066 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6067 if (! fringe_bitmap)
6068
6069
6070 {
6071 if (it && it->bidi_p)
6072 {
6073 it->position = *position;
6074 iterate_out_of_display_property (it);
6075 *position = it->position;
6076 }
6077 return 1;
6078 }
6079
6080 if (it)
6081 {
6082 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6083
6084 if (CONSP (XCDR (XCDR (spec))))
6085 {
6086 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6087 int face_id2;
6088
6089
6090
6091 specpdl_ref count1 = SPECPDL_INDEX ();
6092 specbind (Qinhibit_quit, Qt);
6093 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6094 FRINGE_FACE_ID, false);
6095 unbind_to (count1, Qnil);
6096 if (face_id2 >= 0)
6097 face_id = face_id2;
6098 }
6099
6100
6101
6102 push_it (it, position);
6103
6104 it->area = TEXT_AREA;
6105 it->what = IT_IMAGE;
6106 it->image_id = -1;
6107 it->position = start_pos;
6108 it->object = NILP (object) ? it->w->contents : object;
6109 it->method = GET_FROM_IMAGE;
6110 it->from_overlay = Qnil;
6111 it->face_id = face_id;
6112 it->from_disp_prop_p = true;
6113
6114
6115
6116
6117 *position = start_pos;
6118
6119 if (EQ (XCAR (spec), Qleft_fringe))
6120 {
6121 it->left_user_fringe_bitmap = fringe_bitmap;
6122 it->left_user_fringe_face_id = face_id;
6123 }
6124 else
6125 {
6126 it->right_user_fringe_bitmap = fringe_bitmap;
6127 it->right_user_fringe_face_id = face_id;
6128 }
6129 }
6130 #endif
6131 return 1;
6132 }
6133
6134
6135
6136
6137 location = Qunbound;
6138 if (CONSP (spec) && CONSP (XCAR (spec)))
6139 {
6140 Lisp_Object tem;
6141
6142 value = XCDR (spec);
6143 if (CONSP (value))
6144 value = XCAR (value);
6145
6146 tem = XCAR (spec);
6147 if (EQ (XCAR (tem), Qmargin)
6148 && (tem = XCDR (tem),
6149 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6150 (NILP (tem)
6151 || EQ (tem, Qleft_margin)
6152 || EQ (tem, Qright_margin))))
6153 location = tem;
6154 }
6155
6156 if (BASE_EQ (location, Qunbound))
6157 {
6158 location = Qnil;
6159 value = spec;
6160 }
6161
6162
6163
6164
6165
6166
6167
6168
6169 bool valid_p = (STRINGP (value)
6170 #ifdef HAVE_WINDOW_SYSTEM
6171 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6172 && valid_image_p (value))
6173 #endif
6174 || (CONSP (value) && EQ (XCAR (value), Qspace))
6175 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6176 && valid_xwidget_spec_p (value)));
6177
6178 if (valid_p && display_replaced == 0)
6179 {
6180 int retval = 1;
6181
6182 if (!it)
6183 {
6184
6185
6186
6187 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6188 retval = 2;
6189 return retval;
6190 }
6191
6192
6193
6194 push_it (it, position);
6195 it->from_overlay = overlay;
6196 it->from_disp_prop_p = true;
6197
6198 if (NILP (location))
6199 it->area = TEXT_AREA;
6200 else if (EQ (location, Qleft_margin))
6201 it->area = LEFT_MARGIN_AREA;
6202 else
6203 it->area = RIGHT_MARGIN_AREA;
6204
6205 if (STRINGP (value))
6206 {
6207 it->string = value;
6208 it->multibyte_p = STRING_MULTIBYTE (it->string);
6209 it->current.overlay_string_index = -1;
6210 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6211 it->end_charpos = it->string_nchars = SCHARS (it->string);
6212 it->method = GET_FROM_STRING;
6213 it->stop_charpos = 0;
6214 it->prev_stop = 0;
6215 it->base_level_stop = 0;
6216 it->string_from_display_prop_p = true;
6217 it->cmp_it.id = -1;
6218
6219
6220
6221 if (BUFFERP (object))
6222 *position = start_pos;
6223
6224
6225
6226
6227 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6228 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6229 else
6230 it->paragraph_embedding = L2R;
6231
6232
6233 if (it->bidi_p)
6234 {
6235 it->bidi_it.string.lstring = it->string;
6236 it->bidi_it.string.s = NULL;
6237 it->bidi_it.string.schars = it->end_charpos;
6238 it->bidi_it.string.bufpos = bufpos;
6239 it->bidi_it.string.from_disp_str = true;
6240 it->bidi_it.string.unibyte = !it->multibyte_p;
6241 it->bidi_it.w = it->w;
6242 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6243 }
6244 }
6245 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6246 {
6247 it->method = GET_FROM_STRETCH;
6248 it->object = value;
6249 *position = it->position = start_pos;
6250 retval = 1 + (it->area == TEXT_AREA);
6251 }
6252 else if (valid_xwidget_spec_p (value))
6253 {
6254 it->what = IT_XWIDGET;
6255 it->method = GET_FROM_XWIDGET;
6256 it->position = start_pos;
6257 it->object = NILP (object) ? it->w->contents : object;
6258 *position = start_pos;
6259 it->xwidget = lookup_xwidget (value);
6260 }
6261 #ifdef HAVE_WINDOW_SYSTEM
6262 else
6263 {
6264 specpdl_ref count = SPECPDL_INDEX ();
6265
6266 it->what = IT_IMAGE;
6267
6268
6269
6270 specbind (Qinhibit_quit, Qt);
6271 it->image_id = lookup_image (it->f, value, it->face_id);
6272 unbind_to (count, Qnil);
6273 it->position = start_pos;
6274 it->object = NILP (object) ? it->w->contents : object;
6275 it->method = GET_FROM_IMAGE;
6276
6277
6278
6279
6280 *position = start_pos;
6281 }
6282 #endif
6283
6284 return retval;
6285 }
6286
6287
6288
6289 *position = start_pos;
6290 return 0;
6291 }
6292
6293
6294
6295
6296
6297
6298 bool
6299 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6300 ptrdiff_t charpos, ptrdiff_t bytepos)
6301 {
6302 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6303 struct text_pos position;
6304
6305 SET_TEXT_POS (position, charpos, bytepos);
6306 return (handle_display_spec (NULL, prop, Qnil, overlay,
6307 &position, charpos, frame_window_p)
6308 != 0);
6309 }
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320 static bool
6321 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6322 {
6323 if (EQ (string, prop))
6324 return true;
6325
6326
6327 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6328 {
6329 prop = XCDR (prop);
6330 if (!CONSP (prop))
6331 return false;
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342 prop = XCDR (prop);
6343 }
6344
6345 if (CONSP (prop))
6346
6347 if (EQ (XCAR (prop), Qmargin))
6348 {
6349 prop = XCDR (prop);
6350 if (!CONSP (prop))
6351 return false;
6352
6353 prop = XCDR (prop);
6354 if (!CONSP (prop))
6355 return false;
6356 }
6357
6358 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6359 }
6360
6361
6362
6363
6364 static bool
6365 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6366 {
6367 if (CONSP (prop)
6368 && !EQ (XCAR (prop), Qwhen)
6369 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6370 {
6371
6372 while (CONSP (prop))
6373 {
6374 if (single_display_spec_string_p (XCAR (prop), string))
6375 return true;
6376 prop = XCDR (prop);
6377 }
6378 }
6379 else if (VECTORP (prop))
6380 {
6381
6382 ptrdiff_t i;
6383 for (i = 0; i < ASIZE (prop); ++i)
6384 if (single_display_spec_string_p (AREF (prop, i), string))
6385 return true;
6386 }
6387 else
6388 return single_display_spec_string_p (prop, string);
6389
6390 return false;
6391 }
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403 static ptrdiff_t
6404 string_buffer_position_lim (Lisp_Object string,
6405 ptrdiff_t from, ptrdiff_t to, bool back_p)
6406 {
6407 Lisp_Object limit, prop, pos;
6408 bool found = false;
6409
6410 pos = make_fixnum (max (from, BEGV));
6411
6412 if (!back_p)
6413 {
6414 limit = make_fixnum (min (to, ZV));
6415 while (!found && !EQ (pos, limit))
6416 {
6417 prop = Fget_char_property (pos, Qdisplay, Qnil);
6418 if (!NILP (prop) && display_prop_string_p (prop, string))
6419 found = true;
6420 else
6421 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6422 limit);
6423 }
6424 }
6425 else
6426 {
6427 limit = make_fixnum (max (to, BEGV));
6428 while (!found && !EQ (pos, limit))
6429 {
6430 prop = Fget_char_property (pos, Qdisplay, Qnil);
6431 if (!NILP (prop) && display_prop_string_p (prop, string))
6432 found = true;
6433 else
6434 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6435 limit);
6436 }
6437 }
6438
6439 return found ? XFIXNUM (pos) : 0;
6440 }
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451 static ptrdiff_t
6452 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6453 {
6454 const int MAX_DISTANCE = 1000;
6455 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6456 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6457 forward_limit, false);
6458
6459 if (!found)
6460 {
6461 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6462 found = string_buffer_position_lim (string, around_charpos,
6463 backward_limit, true);
6464 }
6465 return found;
6466 }
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477 static enum prop_handled
6478 handle_composition_prop (struct it *it)
6479 {
6480 Lisp_Object prop, string;
6481 ptrdiff_t pos, pos_byte, start, end;
6482
6483 if (STRINGP (it->string))
6484 {
6485 unsigned char *s;
6486
6487 pos = IT_STRING_CHARPOS (*it);
6488 pos_byte = IT_STRING_BYTEPOS (*it);
6489 string = it->string;
6490 s = SDATA (string) + pos_byte;
6491 if (STRING_MULTIBYTE (string))
6492 it->c = STRING_CHAR (s);
6493 else
6494 it->c = *s;
6495 }
6496 else
6497 {
6498 pos = IT_CHARPOS (*it);
6499 pos_byte = IT_BYTEPOS (*it);
6500 string = Qnil;
6501 it->c = FETCH_CHAR (pos_byte);
6502 }
6503
6504
6505
6506
6507 if (find_composition (pos, -1, &start, &end, &prop, string)
6508 && composition_valid_p (start, end, prop)
6509 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6510 {
6511 if (start < pos)
6512
6513
6514
6515 return HANDLED_NORMALLY;
6516 if (start != pos)
6517 {
6518 if (STRINGP (it->string))
6519 pos_byte = string_char_to_byte (it->string, start);
6520 else
6521 pos_byte = CHAR_TO_BYTE (start);
6522 }
6523 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6524 prop, string);
6525
6526 if (it->cmp_it.id >= 0)
6527 {
6528 it->cmp_it.ch = -1;
6529 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6530 it->cmp_it.nglyphs = -1;
6531 }
6532 }
6533
6534 return HANDLED_NORMALLY;
6535 }
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546 struct overlay_entry
6547 {
6548 Lisp_Object overlay;
6549 Lisp_Object string;
6550 EMACS_INT priority;
6551 bool after_string_p;
6552 };
6553
6554
6555
6556
6557
6558 static enum prop_handled
6559 handle_overlay_change (struct it *it)
6560 {
6561 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6562 return HANDLED_RECOMPUTE_PROPS;
6563 else
6564 return HANDLED_NORMALLY;
6565 }
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575 static void
6576 next_overlay_string (struct it *it)
6577 {
6578 ++it->current.overlay_string_index;
6579 if (it->current.overlay_string_index == it->n_overlay_strings)
6580 {
6581
6582
6583
6584
6585 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6586 pop_it (it);
6587 eassert (it->sp > 0
6588 || (NILP (it->string)
6589 && it->method == GET_FROM_BUFFER
6590 && it->stop_charpos >= BEGV
6591 && it->stop_charpos <= it->end_charpos));
6592 it->current.overlay_string_index = -1;
6593 it->n_overlay_strings = 0;
6594
6595
6596
6597
6598 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6599 pop_it (it);
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6610 it->ignore_overlay_strings_at_pos_p = true;
6611
6612
6613
6614
6615 if (NILP (it->string)
6616 && IT_CHARPOS (*it) >= it->end_charpos
6617 && it->overlay_strings_charpos >= it->end_charpos)
6618 it->overlay_strings_at_end_processed_p = true;
6619
6620
6621
6622
6623
6624
6625
6626 it->overlay_strings_charpos = -1;
6627 }
6628 else
6629 {
6630
6631
6632
6633
6634
6635
6636 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6637
6638 if (it->current.overlay_string_index && i == 0)
6639 load_overlay_strings (it, it->overlay_strings_charpos);
6640
6641
6642
6643 it->string = it->overlay_strings[i];
6644 it->multibyte_p = STRING_MULTIBYTE (it->string);
6645 SET_TEXT_POS (it->current.string_pos, 0, 0);
6646 it->method = GET_FROM_STRING;
6647 it->stop_charpos = 0;
6648 it->end_charpos = SCHARS (it->string);
6649 if (it->cmp_it.stop_pos >= 0)
6650 it->cmp_it.stop_pos = 0;
6651 it->prev_stop = 0;
6652 it->base_level_stop = 0;
6653
6654
6655 if (it->bidi_p)
6656 {
6657 it->bidi_it.string.lstring = it->string;
6658 it->bidi_it.string.s = NULL;
6659 it->bidi_it.string.schars = SCHARS (it->string);
6660 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6661 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6662 it->bidi_it.string.unibyte = !it->multibyte_p;
6663 it->bidi_it.w = it->w;
6664 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6665 }
6666 }
6667
6668 CHECK_IT (it);
6669 }
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688 static int
6689 compare_overlay_entries (const void *e1, const void *e2)
6690 {
6691 struct overlay_entry const *entry1 = e1;
6692 struct overlay_entry const *entry2 = e2;
6693 int result;
6694
6695 if (entry1->after_string_p != entry2->after_string_p)
6696 {
6697
6698
6699 if (EQ (entry1->overlay, entry2->overlay))
6700 result = entry1->after_string_p ? 1 : -1;
6701 else
6702 result = entry1->after_string_p ? -1 : 1;
6703 }
6704 else if (entry1->priority != entry2->priority)
6705 {
6706 if (entry1->after_string_p)
6707
6708 result = entry2->priority < entry1->priority ? -1 : 1;
6709 else
6710
6711 result = entry1->priority < entry2->priority ? -1 : 1;
6712 }
6713 else
6714 result = 0;
6715
6716 return result;
6717 }
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744 static void
6745 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6746 {
6747 ptrdiff_t n = 0;
6748 struct overlay_entry entriesbuf[20];
6749 ptrdiff_t size = ARRAYELTS (entriesbuf);
6750 struct overlay_entry *entries = entriesbuf;
6751 struct itree_node *node;
6752
6753 USE_SAFE_ALLOCA;
6754
6755 if (charpos <= 0)
6756 charpos = IT_CHARPOS (*it);
6757
6758
6759
6760
6761
6762 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6763 do \
6764 { \
6765 Lisp_Object priority; \
6766 \
6767 if (n == size) \
6768 { \
6769 struct overlay_entry *old = entries; \
6770 SAFE_NALLOCA (entries, 2, size); \
6771 memcpy (entries, old, size * sizeof *entries); \
6772 size *= 2; \
6773 } \
6774 \
6775 entries[n].string = (STRING); \
6776 entries[n].overlay = (OVERLAY); \
6777 priority = Foverlay_get ((OVERLAY), Qpriority); \
6778 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6779 entries[n].after_string_p = (AFTER_P); \
6780 ++n; \
6781 } \
6782 while (false)
6783
6784
6785
6786 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6787 {
6788 Lisp_Object overlay = node->data;
6789 eassert (OVERLAYP (overlay));
6790 ptrdiff_t start = node->begin;
6791 ptrdiff_t end = node->end;
6792
6793
6794
6795 if (end != charpos && start != charpos)
6796 continue;
6797
6798
6799 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6800 if (WINDOWP (window) && XWINDOW (window) != it->w)
6801 continue;
6802
6803
6804
6805
6806 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6807 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6808
6809
6810 Lisp_Object str;
6811 if ((start == charpos || (end == charpos && invis != 0))
6812 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6813 && SCHARS (str))
6814 RECORD_OVERLAY_STRING (overlay, str, false);
6815
6816
6817 if ((end == charpos || (start == charpos && invis != 0))
6818 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6819 && SCHARS (str))
6820 RECORD_OVERLAY_STRING (overlay, str, true);
6821 }
6822
6823 #undef RECORD_OVERLAY_STRING
6824
6825
6826 if (n > 1)
6827 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6828
6829
6830 it->n_overlay_strings = n;
6831 it->overlay_strings_charpos = charpos;
6832
6833
6834
6835
6836 ptrdiff_t j = it->current.overlay_string_index;
6837 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6838 {
6839 it->overlay_strings[i] = entries[j].string;
6840 it->string_overlays[i] = entries[j].overlay;
6841 }
6842
6843 CHECK_IT (it);
6844 SAFE_FREE ();
6845 }
6846
6847
6848
6849
6850
6851
6852 static bool
6853 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6854 {
6855
6856
6857
6858
6859
6860
6861
6862 it->current.overlay_string_index = 0;
6863 load_overlay_strings (it, charpos);
6864
6865
6866
6867
6868 if (it->n_overlay_strings)
6869 {
6870
6871
6872
6873 if (compute_stop_p)
6874 compute_stop_pos (it);
6875 eassert (it->face_id >= 0);
6876
6877
6878
6879 eassert (!compute_stop_p || it->sp == 0);
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889 if (!(!it->bidi_p
6890 && STRINGP (it->string) && !SCHARS (it->string)))
6891 push_it (it, NULL);
6892
6893
6894
6895 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6896 it->string = it->overlay_strings[0];
6897 it->from_overlay = Qnil;
6898 it->stop_charpos = 0;
6899 eassert (STRINGP (it->string));
6900 it->end_charpos = SCHARS (it->string);
6901 it->prev_stop = 0;
6902 it->base_level_stop = 0;
6903 it->multibyte_p = STRING_MULTIBYTE (it->string);
6904 it->method = GET_FROM_STRING;
6905 it->from_disp_prop_p = 0;
6906 it->cmp_it.id = -1;
6907
6908
6909
6910 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6911 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6912 else
6913 it->paragraph_embedding = L2R;
6914
6915
6916 if (it->bidi_p)
6917 {
6918 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6919
6920 it->bidi_it.string.lstring = it->string;
6921 it->bidi_it.string.s = NULL;
6922 it->bidi_it.string.schars = SCHARS (it->string);
6923 it->bidi_it.string.bufpos = pos;
6924 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6925 it->bidi_it.string.unibyte = !it->multibyte_p;
6926 it->bidi_it.w = it->w;
6927 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6928 }
6929 return true;
6930 }
6931
6932 it->current.overlay_string_index = -1;
6933 return false;
6934 }
6935
6936 static bool
6937 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6938 {
6939 it->string = Qnil;
6940 it->method = GET_FROM_BUFFER;
6941
6942 get_overlay_strings_1 (it, charpos, true);
6943
6944 CHECK_IT (it);
6945
6946
6947 return STRINGP (it->string);
6948 }
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962 static void
6963 push_it (struct it *it, struct text_pos *position)
6964 {
6965 struct iterator_stack_entry *p;
6966
6967 eassert (it->sp < IT_STACK_SIZE);
6968 p = it->stack + it->sp;
6969
6970 p->stop_charpos = it->stop_charpos;
6971 p->prev_stop = it->prev_stop;
6972 p->base_level_stop = it->base_level_stop;
6973 p->cmp_it = it->cmp_it;
6974 eassert (it->face_id >= 0);
6975 p->face_id = it->face_id;
6976 p->string = it->string;
6977 p->method = it->method;
6978 p->from_overlay = it->from_overlay;
6979 switch (p->method)
6980 {
6981 case GET_FROM_IMAGE:
6982 p->u.image.object = it->object;
6983 p->u.image.image_id = it->image_id;
6984 p->u.image.slice = it->slice;
6985 break;
6986 case GET_FROM_STRETCH:
6987 p->u.stretch.object = it->object;
6988 break;
6989 case GET_FROM_XWIDGET:
6990 p->u.xwidget.object = it->object;
6991 break;
6992 case GET_FROM_BUFFER:
6993 case GET_FROM_DISPLAY_VECTOR:
6994 case GET_FROM_STRING:
6995 case GET_FROM_C_STRING:
6996 break;
6997 default:
6998 emacs_abort ();
6999 }
7000 p->position = position ? *position : it->position;
7001 p->current = it->current;
7002 p->end_charpos = it->end_charpos;
7003 p->string_nchars = it->string_nchars;
7004 p->area = it->area;
7005 p->multibyte_p = it->multibyte_p;
7006 p->avoid_cursor_p = it->avoid_cursor_p;
7007 p->space_width = it->space_width;
7008 p->font_height = it->font_height;
7009 p->voffset = it->voffset;
7010 p->string_from_display_prop_p = it->string_from_display_prop_p;
7011 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
7012 p->display_ellipsis_p = false;
7013 p->line_wrap = it->line_wrap;
7014 p->bidi_p = it->bidi_p;
7015 p->paragraph_embedding = it->paragraph_embedding;
7016 p->from_disp_prop_p = it->from_disp_prop_p;
7017 ++it->sp;
7018
7019
7020 if (it->bidi_p)
7021 bidi_push_it (&it->bidi_it);
7022 }
7023
7024 static void
7025 iterate_out_of_display_property (struct it *it)
7026 {
7027 bool buffer_p = !STRINGP (it->string);
7028 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
7029 ptrdiff_t bob = (buffer_p ? BEGV : 0);
7030
7031 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
7032
7033
7034
7035
7036 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7037 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7038
7039 while (it->bidi_it.charpos >= bob
7040 && it->prev_stop <= it->bidi_it.charpos
7041 && it->bidi_it.charpos < CHARPOS (it->position)
7042 && it->bidi_it.charpos < eob)
7043 bidi_move_to_visually_next (&it->bidi_it);
7044
7045
7046 if (it->bidi_it.charpos > CHARPOS (it->position))
7047 it->prev_stop = CHARPOS (it->position);
7048
7049
7050 if (it->bidi_it.charpos != CHARPOS (it->position))
7051 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7052 if (buffer_p)
7053 it->current.pos = it->position;
7054 else
7055 it->current.string_pos = it->position;
7056 }
7057
7058
7059
7060
7061
7062 static void
7063 restore_face_box_flags (struct it *it, int prev_face_id)
7064 {
7065 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7066
7067 if (face)
7068 {
7069 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7070
7071 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7072 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7073 && (prev_face == NULL
7074 || prev_face->box == FACE_NO_BOX));
7075 it->face_box_p = face->box != FACE_NO_BOX;
7076 }
7077 }
7078
7079
7080
7081
7082
7083
7084
7085 static void
7086 pop_it (struct it *it)
7087 {
7088 struct iterator_stack_entry *p;
7089 bool from_display_prop = it->from_disp_prop_p;
7090 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7091 int prev_face_id = it->face_id;
7092
7093 eassert (it->sp > 0);
7094 --it->sp;
7095 p = it->stack + it->sp;
7096 it->stop_charpos = p->stop_charpos;
7097 it->prev_stop = p->prev_stop;
7098 it->base_level_stop = p->base_level_stop;
7099 it->cmp_it = p->cmp_it;
7100 it->face_id = p->face_id;
7101 it->current = p->current;
7102 it->position = p->position;
7103 it->string = p->string;
7104 it->from_overlay = p->from_overlay;
7105 if (NILP (it->string))
7106 SET_TEXT_POS (it->current.string_pos, -1, -1);
7107 it->method = p->method;
7108 switch (it->method)
7109 {
7110 case GET_FROM_IMAGE:
7111 it->image_id = p->u.image.image_id;
7112 it->object = p->u.image.object;
7113 it->slice = p->u.image.slice;
7114 break;
7115 case GET_FROM_XWIDGET:
7116 it->object = p->u.xwidget.object;
7117 break;
7118 case GET_FROM_STRETCH:
7119 it->object = p->u.stretch.object;
7120 break;
7121 case GET_FROM_BUFFER:
7122 {
7123 restore_face_box_flags (it, prev_face_id);
7124 it->object = it->w->contents;
7125 }
7126 break;
7127 case GET_FROM_STRING:
7128 {
7129 restore_face_box_flags (it, prev_face_id);
7130 it->object = it->string;
7131 }
7132 break;
7133 case GET_FROM_DISPLAY_VECTOR:
7134 if (it->s)
7135 it->method = GET_FROM_C_STRING;
7136 else if (STRINGP (it->string))
7137 it->method = GET_FROM_STRING;
7138 else
7139 {
7140 it->method = GET_FROM_BUFFER;
7141 it->object = it->w->contents;
7142 }
7143 break;
7144 case GET_FROM_C_STRING:
7145 break;
7146 default:
7147 emacs_abort ();
7148 }
7149 it->end_charpos = p->end_charpos;
7150 it->string_nchars = p->string_nchars;
7151 it->area = p->area;
7152 it->multibyte_p = p->multibyte_p;
7153 it->avoid_cursor_p = p->avoid_cursor_p;
7154 it->space_width = p->space_width;
7155 it->font_height = p->font_height;
7156 it->voffset = p->voffset;
7157 it->string_from_display_prop_p = p->string_from_display_prop_p;
7158 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7159 it->line_wrap = p->line_wrap;
7160 it->bidi_p = p->bidi_p;
7161 it->paragraph_embedding = p->paragraph_embedding;
7162 it->from_disp_prop_p = p->from_disp_prop_p;
7163 if (it->bidi_p)
7164 {
7165 bidi_pop_it (&it->bidi_it);
7166
7167
7168
7169
7170
7171
7172
7173 if (from_display_prop
7174 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7175 iterate_out_of_display_property (it);
7176
7177 eassert ((BUFFERP (it->object)
7178 && IT_CHARPOS (*it) == it->bidi_it.charpos
7179 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7180 || (STRINGP (it->object)
7181 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7182 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7183 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7184
7185
7186
7187
7188
7189
7190 || it->sp > 0);
7191 }
7192
7193
7194
7195 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7196 it->ignore_overlay_strings_at_pos_p = false;
7197 }
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207 static void
7208 back_to_previous_line_start (struct it *it)
7209 {
7210 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7211
7212 dec_both (&cp, &bp);
7213 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7214 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7215 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7216 }
7217
7218
7219
7220
7221
7222 static bool
7223 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7224 {
7225 struct itree_node *node;
7226
7227 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7228 {
7229 Lisp_Object overlay = node->data;
7230 eassert (OVERLAYP (overlay));
7231
7232
7233 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7234 if (WINDOWP (window) && XWINDOW (window) != w)
7235 continue;
7236
7237 ptrdiff_t ostart = node->begin;
7238 ptrdiff_t oend = node->end;
7239
7240
7241 if (!((startpos < oend && ostart < endpos)
7242 || (ostart == oend
7243 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7244 continue;
7245
7246 Lisp_Object str;
7247 str = Foverlay_get (overlay, Qbefore_string);
7248 if (STRINGP (str) && SCHARS (str)
7249 && memchr (SDATA (str), '\n', SBYTES (str)))
7250 return true;
7251 str = Foverlay_get (overlay, Qafter_string);
7252 if (STRINGP (str) && SCHARS (str)
7253 && memchr (SDATA (str), '\n', SBYTES (str)))
7254 return true;
7255 }
7256
7257
7258 Lisp_Object cpos = make_fixnum (startpos);
7259 Lisp_Object limpos = make_fixnum (endpos);
7260
7261 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7262 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7263 {
7264 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7265 Lisp_Object string = string_from_display_spec (spec);
7266 if (STRINGP (string)
7267 && memchr (SDATA (string), '\n', SBYTES (string)))
7268 return true;
7269 }
7270
7271 return false;
7272 }
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296 static bool
7297 forward_to_next_line_start (struct it *it, bool *skipped_p,
7298 struct bidi_it *bidi_it_prev)
7299 {
7300 ptrdiff_t old_selective;
7301 bool newline_found_p = false;
7302 int n;
7303 const int MAX_NEWLINE_DISTANCE = 500;
7304
7305
7306
7307 if (it->what == IT_CHARACTER
7308 && it->c == '\n'
7309 && CHARPOS (it->position) == IT_CHARPOS (*it))
7310 {
7311 if (it->bidi_p && bidi_it_prev)
7312 *bidi_it_prev = it->bidi_it;
7313 set_iterator_to_next (it, false);
7314 it->c = 0;
7315 return true;
7316 }
7317
7318
7319
7320
7321
7322 old_selective = it->selective;
7323 it->selective = 0;
7324
7325
7326
7327
7328 for (n = 0;
7329 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7330 n += !STRINGP (it->string))
7331 {
7332 if (!get_next_display_element (it))
7333 return false;
7334 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7335 if (newline_found_p && it->bidi_p && bidi_it_prev)
7336 *bidi_it_prev = it->bidi_it;
7337 set_iterator_to_next (it, false);
7338 }
7339
7340
7341
7342 if (!newline_found_p)
7343 {
7344 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7345 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7346 1, &bytepos);
7347 eassert (!STRINGP (it->string));
7348
7349
7350
7351
7352 bool no_strings_with_newlines = it->stop_charpos >= limit;
7353
7354 if (!no_strings_with_newlines)
7355 {
7356 if (!(current_buffer->long_line_optimizations_p
7357 && it->line_wrap == TRUNCATE))
7358 {
7359
7360
7361 Lisp_Object pos =
7362 Fnext_single_property_change (make_fixnum (start),
7363 Qdisplay, Qnil,
7364 make_fixnum (limit));
7365 no_strings_with_newlines =
7366 (NILP (pos) || XFIXNAT (pos) == limit)
7367 && next_overlay_change (start) == ZV;
7368 }
7369 else
7370 {
7371
7372
7373
7374
7375 no_strings_with_newlines =
7376 !strings_with_newlines (start, limit, it->w);
7377 }
7378 }
7379
7380
7381
7382
7383 if (no_strings_with_newlines)
7384 {
7385 if (!it->bidi_p || !bidi_it_prev)
7386 {
7387
7388 IT_CHARPOS (*it) = limit;
7389 IT_BYTEPOS (*it) = bytepos;
7390 }
7391 else
7392 {
7393
7394
7395
7396 struct bidi_it bprev;
7397
7398
7399
7400
7401 if (it->bidi_it.disp_pos < limit)
7402 {
7403 it->bidi_it.disp_pos = limit;
7404 it->bidi_it.disp_prop = 0;
7405 }
7406 do {
7407 bprev = it->bidi_it;
7408 bidi_move_to_visually_next (&it->bidi_it);
7409 } while (it->bidi_it.charpos != limit);
7410 IT_CHARPOS (*it) = limit;
7411 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7412 if (bidi_it_prev)
7413 *bidi_it_prev = bprev;
7414 }
7415 *skipped_p = newline_found_p = true;
7416 }
7417 else
7418 {
7419
7420 while (!newline_found_p)
7421 {
7422 if (!get_next_display_element (it))
7423 break;
7424 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7425 if (newline_found_p && it->bidi_p && bidi_it_prev)
7426 *bidi_it_prev = it->bidi_it;
7427 set_iterator_to_next (it, false);
7428 }
7429 }
7430 }
7431
7432 it->selective = old_selective;
7433 return newline_found_p;
7434 }
7435
7436
7437
7438
7439
7440
7441
7442 static void
7443 back_to_previous_visible_line_start (struct it *it)
7444 {
7445 while (IT_CHARPOS (*it) > BEGV)
7446 {
7447 back_to_previous_line_start (it);
7448
7449 if (IT_CHARPOS (*it) <= BEGV)
7450 break;
7451
7452
7453
7454 if (it->selective > 0
7455 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7456 it->selective))
7457 continue;
7458
7459
7460 {
7461 Lisp_Object prop;
7462 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7463 Qinvisible, it->window);
7464 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7465 continue;
7466 }
7467
7468 if (IT_CHARPOS (*it) <= BEGV)
7469 break;
7470
7471 {
7472 struct it it2;
7473 void *it2data = NULL;
7474 ptrdiff_t pos;
7475 ptrdiff_t beg, end;
7476 Lisp_Object val, overlay;
7477
7478 SAVE_IT (it2, *it, it2data);
7479
7480
7481 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7482 && beg < IT_CHARPOS (*it))
7483 goto replaced;
7484
7485
7486
7487 pos = --IT_CHARPOS (it2);
7488 --IT_BYTEPOS (it2);
7489 it2.sp = 0;
7490 bidi_unshelve_cache (NULL, false);
7491 it2.string_from_display_prop_p = false;
7492 it2.from_disp_prop_p = false;
7493 if (handle_display_prop (&it2) == HANDLED_RETURN
7494 && !NILP (val = get_char_property_and_overlay
7495 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7496 && (OVERLAYP (overlay)
7497 ? (beg = OVERLAY_START (overlay))
7498 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7499 {
7500 RESTORE_IT (it, it, it2data);
7501 goto replaced;
7502 }
7503
7504
7505 RESTORE_IT (it, it, it2data);
7506 break;
7507
7508 replaced:
7509 if (beg < BEGV)
7510 beg = BEGV;
7511 IT_CHARPOS (*it) = beg;
7512 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7513 }
7514 }
7515
7516 it->continuation_lines_width = 0;
7517
7518 eassert (IT_CHARPOS (*it) >= BEGV);
7519 eassert (it->medium_narrowing_begv > 0
7520 || IT_CHARPOS (*it) == BEGV
7521 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7522 CHECK_IT (it);
7523 }
7524
7525
7526
7527
7528
7529
7530
7531 void
7532 reseat_at_previous_visible_line_start (struct it *it)
7533 {
7534 back_to_previous_visible_line_start (it);
7535 reseat (it, it->current.pos, true);
7536 CHECK_IT (it);
7537 }
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547 static void
7548 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7549 {
7550 bool skipped_p = false;
7551 struct bidi_it bidi_it_prev;
7552 bool newline_found_p
7553 = forward_to_next_line_start (it, &skipped_p,
7554 on_newline_p ? &bidi_it_prev : NULL);
7555
7556
7557
7558 if (it->selective > 0)
7559 while (IT_CHARPOS (*it) < ZV
7560 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7561 it->selective))
7562 {
7563 eassert (IT_BYTEPOS (*it) == BEGV
7564 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7565 newline_found_p =
7566 forward_to_next_line_start (it, &skipped_p,
7567 on_newline_p ? &bidi_it_prev : NULL);
7568 }
7569
7570
7571 if (on_newline_p && newline_found_p)
7572 {
7573 if (STRINGP (it->string))
7574 {
7575 if (IT_STRING_CHARPOS (*it) > 0)
7576 {
7577 if (!it->bidi_p)
7578 {
7579 --IT_STRING_CHARPOS (*it);
7580 --IT_STRING_BYTEPOS (*it);
7581 }
7582 else
7583 {
7584
7585
7586
7587 it->bidi_it = bidi_it_prev;
7588 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7589 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7590 }
7591 }
7592 }
7593 else if (IT_CHARPOS (*it) > BEGV)
7594 {
7595 if (!it->bidi_p)
7596 {
7597 --IT_CHARPOS (*it);
7598 --IT_BYTEPOS (*it);
7599 }
7600 else
7601 {
7602
7603
7604 it->bidi_it = bidi_it_prev;
7605 IT_CHARPOS (*it) = it->bidi_it.charpos;
7606 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7607 }
7608 reseat (it, it->current.pos, false);
7609 }
7610 }
7611 else if (skipped_p)
7612 reseat (it, it->current.pos, false);
7613
7614 CHECK_IT (it);
7615 }
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628 static void
7629 reseat (struct it *it, struct text_pos pos, bool force_p)
7630 {
7631 ptrdiff_t original_pos = IT_CHARPOS (*it);
7632
7633 reseat_1 (it, pos, false);
7634
7635 if (current_buffer->long_line_optimizations_p)
7636 {
7637 if (!it->medium_narrowing_begv)
7638 {
7639 it->medium_narrowing_begv
7640 = get_medium_narrowing_begv (it->w, window_point (it->w));
7641 it->medium_narrowing_zv
7642 = get_medium_narrowing_zv (it->w, window_point (it->w));
7643 it->large_narrowing_begv
7644 = get_large_narrowing_begv (window_point (it->w));
7645 it->large_narrowing_zv
7646 = get_large_narrowing_zv (window_point (it->w));
7647 }
7648 else if ((pos.charpos < it->medium_narrowing_begv
7649 || pos.charpos > it->medium_narrowing_zv)
7650 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7651 {
7652 it->medium_narrowing_begv
7653 = get_medium_narrowing_begv (it->w, pos.charpos);
7654 it->medium_narrowing_zv
7655 = get_medium_narrowing_zv (it->w, pos.charpos);
7656 it->large_narrowing_begv
7657 = get_large_narrowing_begv (window_point (it->w));
7658 it->large_narrowing_zv
7659 = get_large_narrowing_zv (window_point (it->w));
7660 }
7661 }
7662
7663
7664
7665 if (force_p
7666 || CHARPOS (pos) > it->stop_charpos
7667 || CHARPOS (pos) < original_pos)
7668 {
7669 if (it->bidi_p)
7670 {
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681 if (CHARPOS (pos) != it->prev_stop)
7682 it->prev_stop = CHARPOS (pos);
7683 if (CHARPOS (pos) < it->base_level_stop)
7684 it->base_level_stop = 0;
7685 handle_stop (it);
7686 }
7687 else
7688 {
7689 handle_stop (it);
7690 it->prev_stop = it->base_level_stop = 0;
7691 }
7692
7693 }
7694
7695 CHECK_IT (it);
7696 }
7697
7698
7699
7700
7701
7702 static void
7703 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7704 {
7705
7706 eassert (it->s == NULL);
7707
7708
7709 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7710
7711 it->current.pos = it->position = pos;
7712 it->end_charpos = ZV;
7713 it->dpvec = NULL;
7714 it->current.dpvec_index = -1;
7715 it->current.overlay_string_index = -1;
7716 IT_STRING_CHARPOS (*it) = -1;
7717 IT_STRING_BYTEPOS (*it) = -1;
7718 it->string = Qnil;
7719 it->method = GET_FROM_BUFFER;
7720 it->object = it->w->contents;
7721 it->area = TEXT_AREA;
7722 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7723 it->sp = 0;
7724 it->string_from_display_prop_p = false;
7725 it->string_from_prefix_prop_p = false;
7726
7727 it->from_disp_prop_p = false;
7728 it->face_before_selective_p = false;
7729 if (it->bidi_p)
7730 {
7731 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7732 &it->bidi_it);
7733 bidi_unshelve_cache (NULL, false);
7734 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7735 it->bidi_it.string.s = NULL;
7736 it->bidi_it.string.lstring = Qnil;
7737 it->bidi_it.string.bufpos = 0;
7738 it->bidi_it.string.from_disp_str = false;
7739 it->bidi_it.string.unibyte = false;
7740 it->bidi_it.w = it->w;
7741 }
7742
7743 if (set_stop_p)
7744 {
7745 it->stop_charpos = CHARPOS (pos);
7746 it->base_level_stop = CHARPOS (pos);
7747 }
7748
7749 it->cmp_it.id = -1;
7750 it->min_width_property = Qnil;
7751 }
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772 static void
7773 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7774 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7775 int multibyte)
7776 {
7777
7778 it->stop_charpos = -1;
7779
7780
7781 memset (&it->current, 0, sizeof it->current);
7782 it->current.overlay_string_index = -1;
7783 it->current.dpvec_index = -1;
7784 eassert (charpos >= 0);
7785
7786
7787
7788 if (multibyte >= 0)
7789 it->multibyte_p = multibyte > 0;
7790
7791
7792
7793
7794
7795 it->bidi_p =
7796 !redisplay__inhibit_bidi
7797 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7798
7799 if (s == NULL)
7800 {
7801 eassert (STRINGP (string));
7802 it->string = string;
7803 it->s = NULL;
7804 it->end_charpos = it->string_nchars = SCHARS (string);
7805 it->method = GET_FROM_STRING;
7806 it->current.string_pos = string_pos (charpos, string);
7807
7808 if (it->bidi_p)
7809 {
7810 it->bidi_it.string.lstring = string;
7811 it->bidi_it.string.s = NULL;
7812 it->bidi_it.string.schars = it->end_charpos;
7813 it->bidi_it.string.bufpos = 0;
7814 it->bidi_it.string.from_disp_str = false;
7815 it->bidi_it.string.unibyte = !it->multibyte_p;
7816 it->bidi_it.w = it->w;
7817 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7818 FRAME_WINDOW_P (it->f), &it->bidi_it);
7819 }
7820 }
7821 else
7822 {
7823 it->s = (const unsigned char *) s;
7824 it->string = Qnil;
7825
7826
7827
7828 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7829 if (it->multibyte_p)
7830 {
7831 it->current.pos = c_string_pos (charpos, s, true);
7832 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7833 }
7834 else
7835 {
7836 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7837 it->end_charpos = it->string_nchars = strlen (s);
7838 }
7839
7840 if (it->bidi_p)
7841 {
7842 it->bidi_it.string.lstring = Qnil;
7843 it->bidi_it.string.s = (const unsigned char *) s;
7844 it->bidi_it.string.schars = it->end_charpos;
7845 it->bidi_it.string.bufpos = 0;
7846 it->bidi_it.string.from_disp_str = false;
7847 it->bidi_it.string.unibyte = !it->multibyte_p;
7848 it->bidi_it.w = it->w;
7849 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7850 &it->bidi_it);
7851 }
7852 it->method = GET_FROM_C_STRING;
7853 }
7854
7855
7856
7857 if (precision > 0 && it->end_charpos - charpos > precision)
7858 {
7859 it->end_charpos = it->string_nchars = charpos + precision;
7860 if (it->bidi_p)
7861 it->bidi_it.string.schars = it->end_charpos;
7862 }
7863
7864
7865
7866
7867
7868 if (field_width < 0)
7869 field_width = DISP_INFINITY;
7870
7871
7872
7873 if (field_width > it->end_charpos - charpos)
7874 it->end_charpos = charpos + field_width;
7875
7876
7877 if (DISP_TABLE_P (Vstandard_display_table))
7878 it->dp = XCHAR_TABLE (Vstandard_display_table);
7879
7880 it->stop_charpos = charpos;
7881 it->prev_stop = charpos;
7882 it->base_level_stop = 0;
7883 if (it->bidi_p)
7884 {
7885 it->bidi_it.first_elt = true;
7886 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7887 it->bidi_it.disp_pos = -1;
7888 }
7889 if (s == NULL && it->multibyte_p)
7890 {
7891 ptrdiff_t endpos = SCHARS (it->string);
7892 if (endpos > it->end_charpos)
7893 endpos = it->end_charpos;
7894 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7895 it->string, true);
7896 }
7897 CHECK_IT (it);
7898 }
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908 typedef bool (*next_element_function) (struct it *);
7909
7910 static next_element_function const get_next_element[NUM_IT_METHODS] =
7911 {
7912 next_element_from_buffer,
7913 next_element_from_display_vector,
7914 next_element_from_string,
7915 next_element_from_c_string,
7916 next_element_from_image,
7917 next_element_from_stretch,
7918 next_element_from_xwidget,
7919 };
7920
7921 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7933 ((IT)->cmp_it.id >= 0 \
7934 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7935 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7936 END_CHARPOS, (IT)->w, \
7937 (IT)->bidi_p \
7938 ? (IT)->bidi_it.resolved_level \
7939 : -1, \
7940 FACE_FROM_ID_OR_NULL ((IT)->f, \
7941 (IT)->face_id), \
7942 (IT)->string)))
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952 Lisp_Object
7953 lookup_glyphless_char_display (int c, struct it *it)
7954 {
7955 Lisp_Object glyphless_method = Qnil;
7956
7957 if (CHAR_TABLE_P (Vglyphless_char_display)
7958 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7959 {
7960 if (c >= 0)
7961 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7962 else
7963 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7964
7965 if (CONSP (glyphless_method))
7966 glyphless_method = FRAME_WINDOW_P (it->f)
7967 ? XCAR (glyphless_method)
7968 : XCDR (glyphless_method);
7969 }
7970
7971 retry:
7972 if (NILP (glyphless_method))
7973 {
7974 if (c >= 0)
7975
7976 return Qnil;
7977
7978 glyphless_method = Qempty_box;
7979 }
7980 if (EQ (glyphless_method, Qzero_width))
7981 {
7982 if (c >= 0)
7983 return glyphless_method;
7984
7985 glyphless_method = Qempty_box;
7986 }
7987 if (EQ (glyphless_method, Qthin_space))
7988 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7989 else if (EQ (glyphless_method, Qempty_box))
7990 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7991 else if (EQ (glyphless_method, Qhex_code))
7992 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7993 else if (STRINGP (glyphless_method))
7994 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7995 else
7996 {
7997
7998 glyphless_method = Qnil;
7999 goto retry;
8000 }
8001 it->what = IT_GLYPHLESS;
8002 return glyphless_method;
8003 }
8004
8005
8006
8007 static struct frame *last_escape_glyph_frame = NULL;
8008 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8009 static int last_escape_glyph_merged_face_id = 0;
8010
8011 static int
8012 merge_escape_glyph_face (struct it *it)
8013 {
8014 int face_id;
8015
8016 if (it->f == last_escape_glyph_frame
8017 && it->face_id == last_escape_glyph_face_id)
8018 face_id = last_escape_glyph_merged_face_id;
8019 else
8020 {
8021
8022 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
8023 last_escape_glyph_frame = it->f;
8024 last_escape_glyph_face_id = it->face_id;
8025 last_escape_glyph_merged_face_id = face_id;
8026 }
8027 return face_id;
8028 }
8029
8030
8031
8032 static struct frame *last_glyphless_glyph_frame = NULL;
8033 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8034 static int last_glyphless_glyph_merged_face_id = 0;
8035
8036 int
8037 merge_glyphless_glyph_face (struct it *it)
8038 {
8039 int face_id;
8040
8041 if (it->f == last_glyphless_glyph_frame
8042 && it->face_id == last_glyphless_glyph_face_id)
8043 face_id = last_glyphless_glyph_merged_face_id;
8044 else
8045 {
8046
8047 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8048 last_glyphless_glyph_frame = it->f;
8049 last_glyphless_glyph_face_id = it->face_id;
8050 last_glyphless_glyph_merged_face_id = face_id;
8051 }
8052 return face_id;
8053 }
8054
8055
8056
8057
8058 void
8059 forget_escape_and_glyphless_faces (void)
8060 {
8061 last_escape_glyph_frame = NULL;
8062 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8063 last_glyphless_glyph_frame = NULL;
8064 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8065 }
8066
8067
8068
8069
8070
8071 static bool
8072 get_next_display_element (struct it *it)
8073 {
8074
8075
8076
8077
8078 bool success_p;
8079
8080 get_next:
8081 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8082
8083 if (it->what == IT_CHARACTER)
8084 {
8085
8086
8087
8088
8089
8090 if (it->bidi_p && it->bidi_it.type == STRONG_R
8091 && !inhibit_bidi_mirroring)
8092 it->c = bidi_mirror_char (it->c);
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102 if (success_p && it->dpvec == NULL)
8103 {
8104 Lisp_Object dv;
8105 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8106 bool nonascii_space_p = false;
8107 bool nonascii_hyphen_p = false;
8108 int c = it->c;
8109
8110 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8111 {
8112 eassert (SINGLE_BYTE_CHAR_P (c));
8113 if (unibyte_display_via_language_environment)
8114 {
8115 c = DECODE_CHAR (unibyte, c);
8116 if (c < 0)
8117 c = BYTE8_TO_CHAR (it->c);
8118 }
8119 else
8120 c = BYTE8_TO_CHAR (it->c);
8121 }
8122
8123 if (it->dp
8124 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8125 VECTORP (dv)))
8126 {
8127 struct Lisp_Vector *v = XVECTOR (dv);
8128
8129
8130
8131
8132 if (v->header.size)
8133 {
8134 it->dpvec_char_len = it->len;
8135 it->dpvec = v->contents;
8136 it->dpend = v->contents + v->header.size;
8137 it->current.dpvec_index = 0;
8138 it->dpvec_face_id = -1;
8139 it->saved_face_id = it->face_id;
8140 it->method = GET_FROM_DISPLAY_VECTOR;
8141 it->ellipsis_p = false;
8142 }
8143 else
8144 {
8145 set_iterator_to_next (it, false);
8146 }
8147 goto get_next;
8148 }
8149
8150 if (! NILP (lookup_glyphless_char_display (c, it)))
8151 {
8152 if (it->what == IT_GLYPHLESS)
8153 goto done;
8154
8155 set_iterator_to_next (it, false);
8156 goto get_next;
8157 }
8158
8159
8160
8161 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8162 {
8163 if (blankp (c))
8164 nonascii_space_p = true;
8165 else if (c == SOFT_HYPHEN || c == HYPHEN
8166 || c == NON_BREAKING_HYPHEN)
8167 nonascii_hyphen_p = true;
8168 }
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181 if (((c < ' ' || c == 127)
8182 ? (it->area != TEXT_AREA
8183
8184 || (c != '\t'
8185 && it->glyph_row
8186 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8187 || (c != '\n' && c != '\t'))
8188 : (nonascii_space_p
8189 || nonascii_hyphen_p
8190 || CHAR_BYTE8_P (c)
8191 || ! CHAR_PRINTABLE_P (c))))
8192 {
8193
8194
8195
8196
8197
8198
8199 Lisp_Object gc;
8200 int ctl_len;
8201 int face_id;
8202 int lface_id = 0;
8203 int escape_glyph;
8204
8205
8206
8207 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8208 {
8209 int g;
8210
8211 g = '^';
8212
8213 if (it->dp
8214 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8215 {
8216 g = GLYPH_CODE_CHAR (gc);
8217 lface_id = GLYPH_CODE_FACE (gc);
8218 }
8219
8220 face_id = (lface_id
8221 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8222 : merge_escape_glyph_face (it));
8223
8224 XSETINT (it->ctl_chars[0], g);
8225 XSETINT (it->ctl_chars[1], c ^ 0100);
8226 ctl_len = 2;
8227 goto display_control;
8228 }
8229
8230
8231
8232
8233 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8234 {
8235
8236 face_id = merge_faces (it->w, Qnobreak_space, 0,
8237 it->face_id);
8238 XSETINT (it->ctl_chars[0],
8239 nobreak_char_ascii_display ? ' ' : it->c);
8240 ctl_len = 1;
8241 goto display_control;
8242 }
8243
8244
8245
8246
8247 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8248 {
8249
8250 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8251 it->face_id);
8252 XSETINT (it->ctl_chars[0],
8253 nobreak_char_ascii_display ? '-' : it->c);
8254 ctl_len = 1;
8255 goto display_control;
8256 }
8257
8258
8259
8260
8261 escape_glyph = '\\';
8262
8263 if (it->dp
8264 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8265 {
8266 escape_glyph = GLYPH_CODE_CHAR (gc);
8267 lface_id = GLYPH_CODE_FACE (gc);
8268 }
8269
8270 face_id = (lface_id
8271 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8272 : merge_escape_glyph_face (it));
8273
8274
8275
8276 if (nonascii_space_p || nonascii_hyphen_p)
8277 {
8278 XSETINT (it->ctl_chars[0], escape_glyph);
8279 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8280 ctl_len = 2;
8281 goto display_control;
8282 }
8283
8284 {
8285 char str[10];
8286 int len, i;
8287
8288 if (CHAR_BYTE8_P (c))
8289
8290 c = CHAR_TO_BYTE8 (c);
8291 const char *format_string = display_raw_bytes_as_hex
8292 ? "x%02x"
8293 : "%03o";
8294 len = sprintf (str, format_string, c + 0u);
8295
8296 XSETINT (it->ctl_chars[0], escape_glyph);
8297 for (i = 0; i < len; i++)
8298 XSETINT (it->ctl_chars[i + 1], str[i]);
8299 ctl_len = len + 1;
8300 }
8301
8302 display_control:
8303
8304 it->dpvec_char_len = it->len;
8305 it->dpvec = it->ctl_chars;
8306 it->dpend = it->dpvec + ctl_len;
8307 it->current.dpvec_index = 0;
8308 it->dpvec_face_id = face_id;
8309 it->saved_face_id = it->face_id;
8310 it->method = GET_FROM_DISPLAY_VECTOR;
8311 it->ellipsis_p = false;
8312 goto get_next;
8313 }
8314 it->char_to_display = c;
8315 }
8316 else if (success_p)
8317 {
8318 it->char_to_display = it->c;
8319 }
8320 }
8321
8322 #ifdef HAVE_WINDOW_SYSTEM
8323
8324
8325 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8326 && it->multibyte_p
8327 && success_p
8328 && FRAME_WINDOW_P (it->f))
8329 {
8330 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8331
8332 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8333 {
8334
8335 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8336
8337 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8338 }
8339 else
8340 {
8341 ptrdiff_t pos = (it->s ? -1
8342 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8343 : IT_CHARPOS (*it));
8344 int c;
8345
8346 if (it->what == IT_CHARACTER)
8347 c = it->char_to_display;
8348 else
8349 {
8350 struct composition *cmp = composition_table[it->cmp_it.id];
8351 int i;
8352
8353 c = ' ';
8354 for (i = 0; i < cmp->glyph_len; i++)
8355
8356
8357 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8358 break;
8359 }
8360 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8361 }
8362 }
8363 #endif
8364
8365 done:
8366
8367
8368 if (it->face_box_p
8369 && it->s == NULL)
8370 {
8371 if (it->method == GET_FROM_STRING && it->sp)
8372 {
8373 int face_id = underlying_face_id (it);
8374 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8375
8376 if (face)
8377 {
8378 if (face->box == FACE_NO_BOX)
8379 {
8380
8381
8382 int string_face_id = face_after_it_pos (it);
8383 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8384 it->end_of_box_run_p = true;
8385 }
8386
8387
8388
8389 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8390
8391
8392
8393 || (it->what == IT_COMPOSITION
8394 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8395 >= SCHARS (it->string))))
8396
8397
8398 && ((it->current.overlay_string_index >= 0
8399 && (it->current.overlay_string_index
8400 == it->n_overlay_strings - 1))
8401
8402 || it->from_disp_prop_p))
8403 {
8404 ptrdiff_t ignore;
8405 int next_face_id;
8406 bool text_from_string = false;
8407
8408
8409 struct text_pos pos = it->current.pos;
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421 if (it->from_disp_prop_p)
8422 {
8423 int stackp = it->sp - 1;
8424
8425
8426 while (stackp >= 0
8427 && STRINGP ((it->stack + stackp)->string))
8428 stackp--;
8429 if (stackp < 0)
8430 {
8431
8432
8433
8434
8435
8436
8437 text_from_string = true;
8438 pos = it->stack[it->sp - 1].position;
8439 }
8440 else
8441 pos = (it->stack + stackp)->position;
8442 }
8443 else
8444 INC_TEXT_POS (pos, it->multibyte_p);
8445
8446 if (text_from_string)
8447 {
8448 Lisp_Object base_string = it->stack[it->sp - 1].string;
8449
8450 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8451 it->end_of_box_run_p = true;
8452 else
8453 {
8454 next_face_id
8455 = face_at_string_position (it->w, base_string,
8456 CHARPOS (pos), 0,
8457 &ignore, face_id,
8458 false, 0);
8459 if (FACE_FROM_ID (it->f, next_face_id)->box
8460 == FACE_NO_BOX)
8461 it->end_of_box_run_p = true;
8462 }
8463 }
8464 else if (CHARPOS (pos) >= ZV)
8465 it->end_of_box_run_p = true;
8466 else
8467 {
8468 next_face_id =
8469 face_at_buffer_position (it->w, CHARPOS (pos),
8470 &ignore,
8471 CHARPOS (pos)
8472 + TEXT_PROP_DISTANCE_LIMIT,
8473 false, -1, 0);
8474 if (FACE_FROM_ID (it->f, next_face_id)->box
8475 == FACE_NO_BOX)
8476 it->end_of_box_run_p = true;
8477 }
8478 }
8479 }
8480 }
8481
8482
8483 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8484 {
8485 int face_id = face_after_it_pos (it);
8486 if (face_id != it->face_id
8487 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8488 it->end_of_box_run_p = true;
8489 }
8490 }
8491
8492
8493
8494
8495
8496 if (!success_p && it->sp > 0)
8497 {
8498 set_iterator_to_next (it, false);
8499 success_p = get_next_display_element (it);
8500 }
8501
8502
8503 return success_p;
8504 }
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522 void
8523 set_iterator_to_next (struct it *it, bool reseat_p)
8524 {
8525
8526 if (max_redisplay_ticks > 0)
8527 update_redisplay_ticks (1, it->w);
8528
8529 switch (it->method)
8530 {
8531 case GET_FROM_BUFFER:
8532
8533
8534
8535 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8536 reseat_at_next_visible_line_start (it, false);
8537 else if (it->cmp_it.id >= 0)
8538 {
8539
8540 if (! it->bidi_p)
8541 {
8542 IT_CHARPOS (*it) += it->cmp_it.nchars;
8543 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8544 }
8545 else
8546 {
8547 int i;
8548
8549
8550
8551
8552 for (i = 0; i < it->cmp_it.nchars; i++)
8553 bidi_move_to_visually_next (&it->bidi_it);
8554 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8555 IT_CHARPOS (*it) = it->bidi_it.charpos;
8556 }
8557
8558 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8559 && it->cmp_it.to < it->cmp_it.nglyphs)
8560 {
8561
8562
8563 it->cmp_it.from = it->cmp_it.to;
8564 }
8565 else if ((it->bidi_p && it->cmp_it.reversed_p)
8566 && it->cmp_it.from > 0)
8567 {
8568
8569
8570 it->cmp_it.to = it->cmp_it.from;
8571 }
8572 else
8573 {
8574
8575
8576 ptrdiff_t stop = it->end_charpos;
8577
8578 if (it->bidi_it.scan_dir < 0)
8579
8580
8581 stop = -1;
8582 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8583 IT_BYTEPOS (*it), stop, Qnil, true);
8584 }
8585 }
8586 else
8587 {
8588 eassert (it->len != 0);
8589
8590 if (!it->bidi_p)
8591 {
8592 IT_BYTEPOS (*it) += it->len;
8593 IT_CHARPOS (*it) += 1;
8594 }
8595 else
8596 {
8597 int prev_scan_dir = it->bidi_it.scan_dir;
8598
8599
8600 if (it->bidi_it.new_paragraph)
8601 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8602 false);
8603 bidi_move_to_visually_next (&it->bidi_it);
8604 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8605 IT_CHARPOS (*it) = it->bidi_it.charpos;
8606 if (prev_scan_dir != it->bidi_it.scan_dir)
8607 {
8608
8609
8610 ptrdiff_t stop = it->end_charpos;
8611 if (it->bidi_it.scan_dir < 0)
8612 stop = -1;
8613 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8614 IT_BYTEPOS (*it), stop, Qnil,
8615 true);
8616 }
8617 }
8618 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8619 }
8620 break;
8621
8622 case GET_FROM_C_STRING:
8623
8624 if (!it->bidi_p
8625
8626
8627
8628
8629 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8630 {
8631 IT_BYTEPOS (*it) += it->len;
8632 IT_CHARPOS (*it) += 1;
8633 }
8634 else
8635 {
8636 bidi_move_to_visually_next (&it->bidi_it);
8637 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8638 IT_CHARPOS (*it) = it->bidi_it.charpos;
8639 }
8640 break;
8641
8642 case GET_FROM_DISPLAY_VECTOR:
8643
8644
8645
8646
8647 ++it->current.dpvec_index;
8648
8649
8650
8651 it->face_id = it->saved_face_id;
8652
8653 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8654 {
8655 bool recheck_faces = it->ellipsis_p;
8656
8657 if (it->s)
8658 it->method = GET_FROM_C_STRING;
8659 else if (STRINGP (it->string))
8660 it->method = GET_FROM_STRING;
8661 else
8662 {
8663 it->method = GET_FROM_BUFFER;
8664 it->object = it->w->contents;
8665 }
8666
8667 it->dpvec = NULL;
8668 it->current.dpvec_index = -1;
8669
8670
8671 if (it->dpvec_char_len < 0)
8672 reseat_at_next_visible_line_start (it, true);
8673 else if (it->dpvec_char_len > 0)
8674 {
8675 it->len = it->dpvec_char_len;
8676 set_iterator_to_next (it, reseat_p);
8677 }
8678
8679
8680 if (recheck_faces)
8681 {
8682 if (it->method == GET_FROM_STRING)
8683 it->stop_charpos = IT_STRING_CHARPOS (*it);
8684 else
8685 it->stop_charpos = IT_CHARPOS (*it);
8686 }
8687 }
8688 break;
8689
8690 case GET_FROM_STRING:
8691
8692 eassert (it->s == NULL && STRINGP (it->string));
8693
8694
8695
8696
8697
8698 if (it->current.overlay_string_index >= 0)
8699 {
8700
8701
8702
8703 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8704 goto consider_string_end;
8705 }
8706 else
8707 {
8708
8709
8710 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8711 goto consider_string_end;
8712 }
8713 if (it->cmp_it.id >= 0)
8714 {
8715
8716
8717
8718 if (! it->bidi_p)
8719 {
8720 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8721 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8722 }
8723 else
8724 {
8725 int i;
8726
8727 for (i = 0; i < it->cmp_it.nchars; i++)
8728 bidi_move_to_visually_next (&it->bidi_it);
8729 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8730 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8731 }
8732
8733
8734
8735 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8736 && (it->cmp_it.to < it->cmp_it.nglyphs))
8737 {
8738
8739
8740 it->cmp_it.from = it->cmp_it.to;
8741 }
8742 else if ((it->bidi_p && it->cmp_it.reversed_p)
8743 && it->cmp_it.from > 0)
8744 {
8745
8746
8747 it->cmp_it.to = it->cmp_it.from;
8748 }
8749 else
8750 {
8751
8752
8753
8754
8755
8756
8757 ptrdiff_t stop = SCHARS (it->string);
8758
8759 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8760 stop = -1;
8761 else if (it->end_charpos < stop)
8762 {
8763
8764
8765
8766 stop = it->end_charpos;
8767 }
8768 composition_compute_stop_pos (&it->cmp_it,
8769 IT_STRING_CHARPOS (*it),
8770 IT_STRING_BYTEPOS (*it), stop,
8771 it->string, true);
8772 }
8773 }
8774 else
8775 {
8776 if (!it->bidi_p
8777
8778
8779
8780
8781
8782 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8783 {
8784 IT_STRING_BYTEPOS (*it) += it->len;
8785 IT_STRING_CHARPOS (*it) += 1;
8786 }
8787 else
8788 {
8789 int prev_scan_dir = it->bidi_it.scan_dir;
8790
8791 bidi_move_to_visually_next (&it->bidi_it);
8792 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8793 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8794
8795
8796 if (prev_scan_dir != it->bidi_it.scan_dir)
8797 {
8798 ptrdiff_t stop = SCHARS (it->string);
8799
8800 if (it->bidi_it.scan_dir < 0)
8801 stop = -1;
8802 else if (it->end_charpos < stop)
8803 stop = it->end_charpos;
8804
8805 composition_compute_stop_pos (&it->cmp_it,
8806 IT_STRING_CHARPOS (*it),
8807 IT_STRING_BYTEPOS (*it), stop,
8808 it->string, true);
8809 }
8810 }
8811 }
8812
8813 consider_string_end:
8814
8815 if (it->current.overlay_string_index >= 0)
8816 {
8817
8818
8819 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8820 {
8821 it->ellipsis_p = false;
8822 next_overlay_string (it);
8823 if (it->ellipsis_p)
8824 setup_for_ellipsis (it, 0);
8825 }
8826 }
8827 else
8828 {
8829
8830
8831
8832
8833 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8834 && it->sp > 0)
8835 {
8836 pop_it (it);
8837 if (it->method == GET_FROM_STRING)
8838 goto consider_string_end;
8839 }
8840 }
8841 break;
8842
8843 case GET_FROM_IMAGE:
8844 case GET_FROM_STRETCH:
8845 case GET_FROM_XWIDGET:
8846
8847
8848
8849
8850 eassert (it->sp > 0);
8851 pop_it (it);
8852 if (it->method == GET_FROM_STRING)
8853 goto consider_string_end;
8854 break;
8855
8856 default:
8857
8858 emacs_abort ();
8859 }
8860
8861 eassert (it->method != GET_FROM_STRING
8862 || (STRINGP (it->string)
8863 && IT_STRING_CHARPOS (*it) >= 0));
8864 }
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875 static bool
8876 next_element_from_display_vector (struct it *it)
8877 {
8878 Lisp_Object gc;
8879 int prev_face_id = it->face_id;
8880 int next_face_id;
8881
8882
8883 eassert (it->dpvec && it->current.dpvec_index >= 0);
8884
8885 it->face_id = it->saved_face_id;
8886
8887
8888
8889 if (it->dpend - it->dpvec > 0
8890 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8891 {
8892 struct face *this_face, *prev_face, *next_face;
8893
8894 it->c = GLYPH_CODE_CHAR (gc);
8895 it->len = CHAR_BYTES (it->c);
8896
8897
8898
8899
8900 if (it->dpvec_face_id >= 0)
8901 it->face_id = it->dpvec_face_id;
8902 else
8903 {
8904 int lface_id = GLYPH_CODE_FACE (gc);
8905 if (lface_id > 0)
8906 it->face_id = merge_faces (it->w, Qt, lface_id,
8907 it->saved_face_id);
8908 }
8909
8910
8911
8912
8913 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8914 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8915
8916
8917 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8918 && (!prev_face
8919 || prev_face->box == FACE_NO_BOX));
8920
8921
8922
8923
8924 next_face_id = it->saved_face_id;
8925 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8926 {
8927 if (it->dpvec_face_id >= 0)
8928 next_face_id = it->dpvec_face_id;
8929 else
8930 {
8931 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8932 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8933
8934 if (lface_id > 0)
8935 next_face_id = merge_faces (it->w, Qt, lface_id,
8936 it->saved_face_id);
8937 }
8938 }
8939 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8940 if (this_face && this_face->box != FACE_NO_BOX
8941 && (!next_face || next_face->box == FACE_NO_BOX))
8942 it->end_of_box_run_p = true;
8943 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8944 }
8945 else
8946
8947 it->c = ' ', it->len = 1;
8948
8949
8950
8951
8952 it->what = IT_CHARACTER;
8953 return true;
8954 }
8955
8956
8957
8958 static void
8959 get_visually_first_element (struct it *it)
8960 {
8961 bool string_p = STRINGP (it->string) || it->s;
8962 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8963 ptrdiff_t bob;
8964 ptrdiff_t obegv = BEGV;
8965
8966 SET_WITH_NARROWED_BEGV (it, bob,
8967 string_p ? 0 :
8968 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8969 it->medium_narrowing_begv);
8970
8971 if (STRINGP (it->string))
8972 {
8973 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8974 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8975 }
8976 else
8977 {
8978 it->bidi_it.charpos = IT_CHARPOS (*it);
8979 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8980 }
8981
8982 if (it->bidi_it.charpos == eob)
8983 {
8984
8985
8986
8987 it->bidi_it.first_elt = false;
8988 }
8989 else if (it->bidi_it.charpos == bob
8990 || (!string_p
8991 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8992 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8993 {
8994
8995
8996 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8997 bidi_move_to_visually_next (&it->bidi_it);
8998 }
8999 else
9000 {
9001 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
9002
9003
9004
9005
9006 if (string_p)
9007 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
9008 else
9009 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
9010 find_newline_no_quit (IT_CHARPOS (*it),
9011 IT_BYTEPOS (*it), -1,
9012 &it->bidi_it.bytepos),
9013 it->medium_narrowing_begv);
9014 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9015 do
9016 {
9017
9018
9019 bidi_move_to_visually_next (&it->bidi_it);
9020 }
9021 while (it->bidi_it.bytepos != orig_bytepos
9022 && it->bidi_it.charpos < eob);
9023 }
9024
9025
9026 if (STRINGP (it->string))
9027 {
9028 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
9029 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
9030 }
9031 else
9032 {
9033 IT_CHARPOS (*it) = it->bidi_it.charpos;
9034 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9035 }
9036
9037 if (STRINGP (it->string) || !it->s)
9038 {
9039 ptrdiff_t stop, charpos, bytepos;
9040
9041 if (STRINGP (it->string))
9042 {
9043 eassert (!it->s);
9044 stop = SCHARS (it->string);
9045 if (stop > it->end_charpos)
9046 stop = it->end_charpos;
9047 charpos = IT_STRING_CHARPOS (*it);
9048 bytepos = IT_STRING_BYTEPOS (*it);
9049 }
9050 else
9051 {
9052 stop = it->end_charpos;
9053 charpos = IT_CHARPOS (*it);
9054 bytepos = IT_BYTEPOS (*it);
9055 }
9056 if (it->bidi_it.scan_dir < 0)
9057 stop = -1;
9058 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9059 it->string, true);
9060 }
9061 }
9062
9063
9064
9065
9066
9067
9068 static bool
9069 next_element_from_string (struct it *it)
9070 {
9071 struct text_pos position;
9072
9073 eassert (STRINGP (it->string));
9074 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9075 eassert (IT_STRING_CHARPOS (*it) >= 0);
9076 position = it->current.string_pos;
9077
9078
9079
9080
9081
9082 if (it->bidi_p && it->bidi_it.first_elt)
9083 {
9084 get_visually_first_element (it);
9085 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9086 }
9087
9088
9089 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9090 {
9091 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9092 {
9093 if (!(!it->bidi_p
9094 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9095 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9096 {
9097
9098
9099
9100
9101
9102
9103 handle_stop_backwards (it, it->stop_charpos);
9104 return GET_NEXT_DISPLAY_ELEMENT (it);
9105 }
9106 else
9107 {
9108 if (it->bidi_p)
9109 {
9110
9111
9112 it->prev_stop = it->stop_charpos;
9113
9114
9115
9116 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9117 it->base_level_stop = it->stop_charpos;
9118 }
9119 handle_stop (it);
9120
9121
9122
9123 return GET_NEXT_DISPLAY_ELEMENT (it);
9124 }
9125 }
9126 else if (it->bidi_p
9127
9128
9129
9130 && IT_STRING_CHARPOS (*it) < it->prev_stop
9131
9132
9133
9134
9135 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9136 {
9137
9138
9139
9140
9141 if (it->base_level_stop <= 0
9142 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9143 it->base_level_stop = 0;
9144 handle_stop_backwards (it, it->base_level_stop);
9145 return GET_NEXT_DISPLAY_ELEMENT (it);
9146 }
9147 }
9148
9149 if (it->current.overlay_string_index >= 0)
9150 {
9151
9152
9153
9154 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9155 {
9156 it->what = IT_EOB;
9157 return false;
9158 }
9159 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9160 IT_STRING_BYTEPOS (*it),
9161 it->bidi_it.scan_dir < 0
9162 ? -1
9163 : SCHARS (it->string))
9164 && next_element_from_composition (it))
9165 {
9166 return true;
9167 }
9168 else if (STRING_MULTIBYTE (it->string))
9169 {
9170 const unsigned char *s = (SDATA (it->string)
9171 + IT_STRING_BYTEPOS (*it));
9172 it->c = check_char_and_length (s, &it->len);
9173 }
9174 else
9175 {
9176 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9177 it->len = 1;
9178 }
9179 }
9180 else
9181 {
9182
9183
9184
9185
9186 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9187 {
9188 it->what = IT_EOB;
9189 return false;
9190 }
9191 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9192 {
9193
9194 it->c = ' ', it->len = 1;
9195 CHARPOS (position) = BYTEPOS (position) = -1;
9196 }
9197 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9198 IT_STRING_BYTEPOS (*it),
9199 it->bidi_it.scan_dir < 0
9200 ? -1
9201 : it->string_nchars)
9202 && next_element_from_composition (it))
9203 {
9204 return true;
9205 }
9206 else if (STRING_MULTIBYTE (it->string))
9207 {
9208 const unsigned char *s = (SDATA (it->string)
9209 + IT_STRING_BYTEPOS (*it));
9210 it->c = check_char_and_length (s, &it->len);
9211 }
9212 else
9213 {
9214 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9215 it->len = 1;
9216 }
9217 }
9218
9219
9220 it->what = IT_CHARACTER;
9221 it->object = it->string;
9222 it->position = position;
9223 return true;
9224 }
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234 static bool
9235 next_element_from_c_string (struct it *it)
9236 {
9237 bool success_p = true;
9238
9239 eassert (it->s);
9240 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9241 it->what = IT_CHARACTER;
9242 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9243 it->object = make_fixnum (0);
9244
9245
9246
9247
9248
9249 if (it->bidi_p && it->bidi_it.first_elt)
9250 get_visually_first_element (it);
9251
9252
9253
9254
9255 if (IT_CHARPOS (*it) >= it->end_charpos)
9256 {
9257
9258 it->what = IT_EOB;
9259 success_p = false;
9260 }
9261 else if (IT_CHARPOS (*it) >= it->string_nchars)
9262 {
9263
9264 it->c = ' ', it->len = 1;
9265 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9266 }
9267 else if (it->multibyte_p)
9268 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9269 else
9270 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9271
9272 return success_p;
9273 }
9274
9275
9276
9277
9278
9279
9280
9281 static bool
9282 next_element_from_ellipsis (struct it *it)
9283 {
9284 if (it->selective_display_ellipsis_p)
9285 setup_for_ellipsis (it, it->len);
9286 else
9287 {
9288
9289
9290
9291
9292 it->saved_face_id = it->face_id;
9293 it->method = GET_FROM_BUFFER;
9294 it->object = it->w->contents;
9295 reseat_at_next_visible_line_start (it, true);
9296 it->face_before_selective_p = true;
9297 }
9298
9299 return GET_NEXT_DISPLAY_ELEMENT (it);
9300 }
9301
9302
9303
9304
9305
9306
9307
9308 static bool
9309 next_element_from_image (struct it *it)
9310 {
9311 it->what = IT_IMAGE;
9312 return true;
9313 }
9314
9315 static bool
9316 next_element_from_xwidget (struct it *it)
9317 {
9318 it->what = IT_XWIDGET;
9319 return true;
9320 }
9321
9322
9323
9324
9325
9326
9327 static bool
9328 next_element_from_stretch (struct it *it)
9329 {
9330 it->what = IT_STRETCH;
9331 return true;
9332 }
9333
9334
9335
9336
9337
9338
9339 static void
9340 compute_stop_pos_backwards (struct it *it)
9341 {
9342 const int SCAN_BACK_LIMIT = 1000;
9343 struct text_pos pos;
9344 struct display_pos save_current = it->current;
9345 struct text_pos save_position = it->position;
9346 ptrdiff_t charpos = IT_CHARPOS (*it);
9347 ptrdiff_t where_we_are = charpos;
9348 ptrdiff_t save_stop_pos = it->stop_charpos;
9349 ptrdiff_t save_end_pos = it->end_charpos;
9350
9351 eassert (NILP (it->string) && !it->s);
9352 eassert (it->bidi_p);
9353 it->bidi_p = false;
9354 do
9355 {
9356 it->end_charpos = min (charpos + 1, ZV);
9357 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9358 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9359 reseat_1 (it, pos, false);
9360 compute_stop_pos (it);
9361
9362 if (it->stop_charpos <= charpos)
9363 emacs_abort ();
9364 }
9365 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9366
9367 if (it->stop_charpos <= where_we_are)
9368 it->prev_stop = it->stop_charpos;
9369 else
9370 it->prev_stop = BEGV;
9371 it->bidi_p = true;
9372 it->current = save_current;
9373 it->position = save_position;
9374 it->stop_charpos = save_stop_pos;
9375 it->end_charpos = save_end_pos;
9376 }
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386 static void
9387 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9388 {
9389 bool bufp = !STRINGP (it->string);
9390 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9391 struct display_pos save_current = it->current;
9392 struct text_pos save_position = it->position;
9393 struct composition_it save_cmp_it = it->cmp_it;
9394 struct text_pos pos1;
9395 ptrdiff_t next_stop;
9396
9397
9398 eassert (it->bidi_p);
9399 it->bidi_p = false;
9400 do
9401 {
9402 it->prev_stop = charpos;
9403 if (bufp)
9404 {
9405 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9406 reseat_1 (it, pos1, false);
9407 }
9408 else
9409 it->current.string_pos = string_pos (charpos, it->string);
9410 compute_stop_pos (it);
9411
9412 if (it->stop_charpos <= it->prev_stop)
9413 emacs_abort ();
9414 charpos = it->stop_charpos;
9415 }
9416 while (charpos <= where_we_are);
9417
9418 it->bidi_p = true;
9419 it->current = save_current;
9420 it->position = save_position;
9421 it->cmp_it = save_cmp_it;
9422 next_stop = it->stop_charpos;
9423 it->stop_charpos = it->prev_stop;
9424 handle_stop (it);
9425 it->stop_charpos = next_stop;
9426 }
9427
9428
9429
9430
9431
9432
9433 static bool
9434 next_element_from_buffer (struct it *it)
9435 {
9436 bool success_p = true;
9437
9438 eassert (IT_CHARPOS (*it) >= BEGV);
9439 eassert (NILP (it->string) && !it->s);
9440 eassert (!it->bidi_p
9441 || (NILP (it->bidi_it.string.lstring)
9442 && it->bidi_it.string.s == NULL));
9443
9444
9445
9446
9447
9448 if (it->bidi_p && it->bidi_it.first_elt)
9449 {
9450 get_visually_first_element (it);
9451 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9452 }
9453
9454 if (IT_CHARPOS (*it) >= it->stop_charpos)
9455 {
9456 if (IT_CHARPOS (*it) >= it->end_charpos)
9457 {
9458 bool overlay_strings_follow_p;
9459
9460
9461
9462 if (it->overlay_strings_at_end_processed_p)
9463 overlay_strings_follow_p = false;
9464 else
9465 {
9466 it->overlay_strings_at_end_processed_p = true;
9467 overlay_strings_follow_p = get_overlay_strings (it, 0);
9468 }
9469
9470 if (overlay_strings_follow_p)
9471 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9472 else
9473 {
9474 it->what = IT_EOB;
9475 it->position = it->current.pos;
9476 success_p = false;
9477 }
9478 }
9479 else if (!(!it->bidi_p
9480 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9481 || IT_CHARPOS (*it) == it->stop_charpos))
9482 {
9483
9484
9485
9486
9487
9488
9489 handle_stop_backwards (it, it->stop_charpos);
9490 it->ignore_overlay_strings_at_pos_p = false;
9491 return GET_NEXT_DISPLAY_ELEMENT (it);
9492 }
9493 else
9494 {
9495 if (it->bidi_p)
9496 {
9497
9498
9499 it->prev_stop = it->stop_charpos;
9500
9501
9502
9503 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9504 it->base_level_stop = it->stop_charpos;
9505 }
9506 handle_stop (it);
9507 it->ignore_overlay_strings_at_pos_p = false;
9508 return GET_NEXT_DISPLAY_ELEMENT (it);
9509 }
9510 }
9511 else if (it->bidi_p
9512
9513
9514
9515 && IT_CHARPOS (*it) < it->prev_stop
9516
9517
9518
9519
9520 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9521 {
9522 if (it->base_level_stop <= 0
9523 || IT_CHARPOS (*it) < it->base_level_stop)
9524 {
9525
9526
9527
9528
9529 it->base_level_stop = BEGV;
9530 compute_stop_pos_backwards (it);
9531 handle_stop_backwards (it, it->prev_stop);
9532 }
9533 else
9534 handle_stop_backwards (it, it->base_level_stop);
9535 it->ignore_overlay_strings_at_pos_p = false;
9536 return GET_NEXT_DISPLAY_ELEMENT (it);
9537 }
9538 else
9539 {
9540
9541
9542 unsigned char *p;
9543 ptrdiff_t stop;
9544
9545
9546
9547 it->ignore_overlay_strings_at_pos_p = false;
9548
9549 if (composition_break_at_point
9550 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9551 && !NILP (Vauto_composition_mode))
9552 {
9553
9554 if (it->bidi_it.scan_dir < 0)
9555 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9556 else
9557 stop = (IT_CHARPOS (*it) < PT
9558 && PT < it->end_charpos) ? PT : it->end_charpos;
9559 }
9560 else
9561 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9562 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9563 stop)
9564 && next_element_from_composition (it))
9565 {
9566 return true;
9567 }
9568
9569
9570 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9571 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9572 it->c = string_char_and_length (p, &it->len);
9573 else
9574 it->c = *p, it->len = 1;
9575
9576
9577 it->what = IT_CHARACTER;
9578 it->object = it->w->contents;
9579 it->position = it->current.pos;
9580
9581
9582
9583 if (it->selective)
9584 {
9585 if (it->c == '\n')
9586 {
9587
9588
9589 if (it->selective > 0
9590 && IT_CHARPOS (*it) + 1 < ZV
9591 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9592 IT_BYTEPOS (*it) + 1,
9593 it->selective))
9594 {
9595 success_p = next_element_from_ellipsis (it);
9596 it->dpvec_char_len = -1;
9597 }
9598 }
9599 else if (it->c == '\r' && it->selective == -1)
9600 {
9601
9602
9603
9604 success_p = next_element_from_ellipsis (it);
9605 it->dpvec_char_len = -1;
9606 }
9607 }
9608 }
9609
9610
9611 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9612 return success_p;
9613 }
9614
9615
9616
9617
9618
9619
9620
9621 static bool
9622 next_element_from_composition (struct it *it)
9623 {
9624 it->what = IT_COMPOSITION;
9625 it->len = it->cmp_it.nbytes;
9626 if (STRINGP (it->string))
9627 {
9628 if (it->c < 0)
9629 {
9630 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9631 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9632 return false;
9633 }
9634 it->position = it->current.string_pos;
9635 it->object = it->string;
9636 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9637 IT_STRING_BYTEPOS (*it), it->string);
9638 }
9639 else
9640 {
9641 if (it->c < 0)
9642 {
9643 IT_CHARPOS (*it) += it->cmp_it.nchars;
9644 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9645 if (it->bidi_p)
9646 {
9647 if (it->bidi_it.new_paragraph)
9648 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9649 false);
9650
9651
9652 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9653 bidi_move_to_visually_next (&it->bidi_it);
9654 }
9655 return false;
9656 }
9657 it->position = it->current.pos;
9658 it->object = it->w->contents;
9659 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9660 IT_BYTEPOS (*it), Qnil);
9661 }
9662 return true;
9663 }
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9675 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711 static enum move_it_result
9712 move_it_in_display_line_to (struct it *it,
9713 ptrdiff_t to_charpos, int to_x,
9714 enum move_operation_enum op)
9715 {
9716 enum move_it_result result = MOVE_UNDEFINED;
9717 struct glyph_row *saved_glyph_row;
9718 struct it wrap_it, atpos_it, atx_it, ppos_it;
9719 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9720 void *ppos_data = NULL;
9721 bool may_wrap = false;
9722 enum it_method prev_method = it->method;
9723 ptrdiff_t closest_pos UNINIT;
9724 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9725 bool saw_smaller_pos = prev_pos < to_charpos;
9726 bool line_number_pending = false;
9727
9728
9729 saved_glyph_row = it->glyph_row;
9730 it->glyph_row = NULL;
9731
9732
9733
9734
9735
9736
9737 wrap_it.sp = -1;
9738 atpos_it.sp = -1;
9739 atx_it.sp = -1;
9740
9741
9742
9743
9744
9745
9746
9747
9748 if (it->bidi_p)
9749 {
9750 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9751 {
9752 SAVE_IT (ppos_it, *it, ppos_data);
9753 closest_pos = IT_CHARPOS (*it);
9754 }
9755 else
9756 closest_pos = ZV;
9757 }
9758
9759 #define BUFFER_POS_REACHED_P() \
9760 ((op & MOVE_TO_POS) != 0 \
9761 && BUFFERP (it->object) \
9762 && (IT_CHARPOS (*it) == to_charpos \
9763 || ((!it->bidi_p \
9764 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9765 && IT_CHARPOS (*it) > to_charpos) \
9766 || (it->what == IT_COMPOSITION \
9767 && ((IT_CHARPOS (*it) > to_charpos \
9768 && to_charpos >= it->cmp_it.charpos) \
9769 || (IT_CHARPOS (*it) < to_charpos \
9770 && to_charpos <= it->cmp_it.charpos)))) \
9771 && (it->method == GET_FROM_BUFFER \
9772 || (it->method == GET_FROM_DISPLAY_VECTOR \
9773 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9774
9775 if (it->hpos == 0)
9776 {
9777
9778
9779
9780
9781 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9782 && should_produce_line_number (it))
9783 {
9784 if (it->current_x == it->first_visible_x)
9785 maybe_produce_line_number (it);
9786 else
9787 line_number_pending = true;
9788 }
9789
9790 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9791 handle_line_prefix (it);
9792 }
9793
9794 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9795 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9796
9797 while (true)
9798 {
9799 int x, i, ascent = 0, descent = 0;
9800
9801
9802 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9803 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9804 (IT)->max_descent = descent)
9805
9806
9807
9808 if ((op & MOVE_TO_POS) != 0
9809 && BUFFERP (it->object)
9810 && it->method == GET_FROM_BUFFER
9811 && (((!it->bidi_p
9812
9813
9814
9815
9816 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9817 && IT_CHARPOS (*it) > to_charpos)
9818 || (it->bidi_p
9819 && (prev_method == GET_FROM_IMAGE
9820 || prev_method == GET_FROM_STRETCH
9821 || prev_method == GET_FROM_STRING)
9822
9823 && ((prev_pos < to_charpos
9824 && IT_CHARPOS (*it) >= to_charpos)
9825
9826 || (prev_pos > to_charpos
9827 && IT_CHARPOS (*it) <= to_charpos)))))
9828 {
9829 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9830 {
9831 result = MOVE_POS_MATCH_OR_ZV;
9832 break;
9833 }
9834 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9835
9836
9837
9838 SAVE_IT (atpos_it, *it, atpos_data);
9839 }
9840
9841
9842
9843
9844
9845 if (!get_next_display_element (it))
9846 {
9847 result = MOVE_POS_MATCH_OR_ZV;
9848 break;
9849 }
9850
9851 if (it->line_wrap == TRUNCATE)
9852 {
9853
9854
9855
9856
9857
9858
9859 if (BUFFER_POS_REACHED_P ()
9860 && (it->pixel_width > 0
9861 || IT_CHARPOS (*it) > to_charpos
9862 || it->area != TEXT_AREA))
9863 {
9864 result = MOVE_POS_MATCH_OR_ZV;
9865 break;
9866 }
9867 }
9868 else
9869 {
9870 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9871 {
9872 bool next_may_wrap = may_wrap;
9873
9874 if (char_can_wrap_after (it))
9875 next_may_wrap = true;
9876 else
9877 next_may_wrap = false;
9878
9879 if (may_wrap && char_can_wrap_before (it))
9880 {
9881
9882
9883
9884
9885
9886 if (atpos_it.sp >= 0)
9887 {
9888 RESTORE_IT (it, &atpos_it, atpos_data);
9889 result = MOVE_POS_MATCH_OR_ZV;
9890 goto done;
9891 }
9892 if (atx_it.sp >= 0)
9893 {
9894 RESTORE_IT (it, &atx_it, atx_data);
9895 result = MOVE_X_REACHED;
9896 goto done;
9897 }
9898
9899 SAVE_IT (wrap_it, *it, wrap_data);
9900 }
9901
9902 may_wrap = next_may_wrap;
9903 }
9904 }
9905
9906
9907
9908 ascent = it->max_ascent;
9909 descent = it->max_descent;
9910
9911
9912
9913
9914
9915 x = it->current_x;
9916
9917 PRODUCE_GLYPHS (it);
9918
9919 if (it->area != TEXT_AREA)
9920 {
9921 prev_method = it->method;
9922 if (it->method == GET_FROM_BUFFER)
9923 prev_pos = IT_CHARPOS (*it);
9924 set_iterator_to_next (it, true);
9925 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9926 SET_TEXT_POS (this_line_min_pos,
9927 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9928 if (it->bidi_p
9929 && (op & MOVE_TO_POS)
9930 && IT_CHARPOS (*it) > to_charpos
9931 && IT_CHARPOS (*it) < closest_pos)
9932 closest_pos = IT_CHARPOS (*it);
9933 continue;
9934 }
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954 if (it->nglyphs)
9955 {
9956
9957
9958 int single_glyph_width = it->pixel_width / it->nglyphs;
9959 int new_x;
9960 int x_before_this_char = x;
9961 int hpos_before_this_char = it->hpos;
9962
9963 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9964 {
9965 new_x = x + single_glyph_width;
9966
9967
9968 if ((op & MOVE_TO_X) && new_x > to_x)
9969 {
9970 if (BUFFER_POS_REACHED_P ())
9971 {
9972 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9973 goto buffer_pos_reached;
9974 if (atpos_it.sp < 0)
9975 {
9976 SAVE_IT (atpos_it, *it, atpos_data);
9977 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9978 }
9979 }
9980 else
9981 {
9982 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9983 {
9984 it->current_x = x;
9985 result = MOVE_X_REACHED;
9986 break;
9987 }
9988 if (atx_it.sp < 0)
9989 {
9990 SAVE_IT (atx_it, *it, atx_data);
9991 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9992 }
9993 }
9994 }
9995
9996 if (
9997 it->line_wrap != TRUNCATE
9998 && (
9999 new_x > it->last_visible_x
10000
10001
10002 || (new_x == it->last_visible_x
10003 && FRAME_WINDOW_P (it->f)
10004 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10005 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10006 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
10007 {
10008 bool moved_forward = false;
10009
10010 if (
10011
10012 it->hpos == 0
10013 || (new_x == it->last_visible_x
10014 && FRAME_WINDOW_P (it->f)))
10015 {
10016 ++it->hpos;
10017 it->current_x = new_x;
10018
10019
10020
10021 if (i == it->nglyphs - 1)
10022 {
10023
10024
10025
10026 if (BUFFER_POS_REACHED_P ())
10027 {
10028 bool can_wrap = true;
10029
10030
10031
10032
10033
10034 if (it->line_wrap == WORD_WRAP
10035 && wrap_it.sp >= 0
10036 && may_wrap
10037 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10038 {
10039 struct it tem_it;
10040 void *tem_data = NULL;
10041
10042 SAVE_IT (tem_it, *it, tem_data);
10043 set_iterator_to_next (it, true);
10044 if (get_next_display_element (it)
10045 && !char_can_wrap_before (it))
10046 can_wrap = false;
10047 RESTORE_IT (it, &tem_it, tem_data);
10048 }
10049 if (it->line_wrap != WORD_WRAP
10050 || wrap_it.sp < 0
10051
10052
10053
10054
10055
10056
10057
10058 || (may_wrap && can_wrap
10059 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10060 {
10061 it->hpos = hpos_before_this_char;
10062 it->current_x = x_before_this_char;
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 if (it->line_wrap == WORD_WRAP
10067 && atpos_it.sp < 0)
10068 {
10069 SAVE_IT (atpos_it, *it, atpos_data);
10070 atpos_it.current_x = x_before_this_char;
10071 atpos_it.hpos = hpos_before_this_char;
10072 }
10073 }
10074
10075 prev_method = it->method;
10076 if (it->method == GET_FROM_BUFFER)
10077 prev_pos = IT_CHARPOS (*it);
10078 set_iterator_to_next (it, true);
10079 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10080 SET_TEXT_POS (this_line_min_pos,
10081 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10082
10083
10084
10085
10086
10087
10088
10089 if (!FRAME_WINDOW_P (it->f)
10090 || ((it->bidi_p
10091 && it->bidi_it.paragraph_dir == R2L)
10092 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10093 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10094 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10095 {
10096 if (!get_next_display_element (it))
10097 {
10098 result = MOVE_POS_MATCH_OR_ZV;
10099 break;
10100 }
10101 moved_forward = true;
10102 if (BUFFER_POS_REACHED_P ())
10103 {
10104 if (ITERATOR_AT_END_OF_LINE_P (it))
10105 result = MOVE_POS_MATCH_OR_ZV;
10106 else
10107 result = MOVE_LINE_CONTINUED;
10108 break;
10109 }
10110 if (ITERATOR_AT_END_OF_LINE_P (it)
10111 && (it->line_wrap != WORD_WRAP
10112 || wrap_it.sp < 0
10113 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10114 {
10115 result = MOVE_NEWLINE_OR_CR;
10116 break;
10117 }
10118 }
10119 }
10120 }
10121 else
10122 IT_RESET_X_ASCENT_DESCENT (it);
10123
10124
10125
10126
10127
10128
10129 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10130
10131
10132
10133
10134
10135 && (!moved_forward || char_can_wrap_before (it)))
10136 {
10137
10138
10139 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10140 && atx_it.sp >= 0)
10141 {
10142 RESTORE_IT (it, &atx_it, atx_data);
10143 atpos_it.sp = -1;
10144 atx_it.sp = -1;
10145 result = MOVE_X_REACHED;
10146 break;
10147 }
10148 }
10149 else if (wrap_it.sp >= 0)
10150 {
10151 RESTORE_IT (it, &wrap_it, wrap_data);
10152 atpos_it.sp = -1;
10153 atx_it.sp = -1;
10154 }
10155
10156 move_trace ("move_it_in: continued at %td\n",
10157 IT_CHARPOS (*it));
10158 result = MOVE_LINE_CONTINUED;
10159 break;
10160 }
10161
10162 if (BUFFER_POS_REACHED_P ())
10163 {
10164 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10165 goto buffer_pos_reached;
10166 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10167 {
10168 SAVE_IT (atpos_it, *it, atpos_data);
10169 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10170 }
10171 }
10172
10173 if (new_x > it->first_visible_x)
10174 {
10175
10176
10177 if (line_number_pending)
10178 {
10179 line_number_pending = false;
10180 it->current_x = it->first_visible_x;
10181 maybe_produce_line_number (it);
10182 it->current_x += new_x - it->first_visible_x;
10183 }
10184
10185
10186 ++it->hpos;
10187 }
10188 }
10189
10190 if (result != MOVE_UNDEFINED)
10191 break;
10192 }
10193 else if (BUFFER_POS_REACHED_P ())
10194 {
10195 buffer_pos_reached:
10196 IT_RESET_X_ASCENT_DESCENT (it);
10197 result = MOVE_POS_MATCH_OR_ZV;
10198 break;
10199 }
10200 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10201 {
10202
10203
10204
10205
10206 eassert (it->nglyphs == 0);
10207 result = MOVE_X_REACHED;
10208 break;
10209 }
10210
10211
10212 if (ITERATOR_AT_END_OF_LINE_P (it))
10213 {
10214
10215
10216
10217
10218 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10219 {
10220 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10221 {
10222 if (closest_pos < ZV)
10223 {
10224 RESTORE_IT (it, &ppos_it, ppos_data);
10225
10226
10227 if (closest_pos != to_charpos)
10228 move_it_in_display_line_to (it, closest_pos, -1,
10229 MOVE_TO_POS);
10230 result = MOVE_POS_MATCH_OR_ZV;
10231 }
10232 else
10233 goto buffer_pos_reached;
10234 }
10235 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10236 && IT_CHARPOS (*it) > to_charpos)
10237 goto buffer_pos_reached;
10238 else
10239 result = MOVE_NEWLINE_OR_CR;
10240 }
10241 else
10242 result = MOVE_NEWLINE_OR_CR;
10243
10244
10245
10246
10247 if (it->line_wrap == TRUNCATE
10248 && it->current_x <= it->first_visible_x
10249 && result == MOVE_NEWLINE_OR_CR
10250 && it->char_to_display == '\n')
10251 {
10252 it->max_ascent = it->ascent;
10253 it->max_descent = it->descent;
10254 }
10255
10256
10257
10258 if (result == MOVE_NEWLINE_OR_CR)
10259 it->constrain_row_ascent_descent_p = false;
10260 break;
10261 }
10262
10263 prev_method = it->method;
10264 if (it->method == GET_FROM_BUFFER)
10265 prev_pos = IT_CHARPOS (*it);
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275 bool overwide_wrap_prefix =
10276 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10277 && it->sp > 0 && it->method == GET_FROM_STRETCH
10278 && it->current_x >= it->last_visible_x
10279 && it->continuation_lines_width > 0
10280 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10281
10282
10283 if (!overwide_wrap_prefix)
10284 set_iterator_to_next (it, true);
10285 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10286 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10287 if (IT_CHARPOS (*it) < to_charpos)
10288 saw_smaller_pos = true;
10289 if (it->bidi_p
10290 && (op & MOVE_TO_POS)
10291 && IT_CHARPOS (*it) >= to_charpos
10292 && IT_CHARPOS (*it) < closest_pos)
10293 closest_pos = IT_CHARPOS (*it);
10294
10295
10296
10297 if (it->line_wrap == TRUNCATE
10298 && it->current_x >= it->last_visible_x)
10299 {
10300 if (!FRAME_WINDOW_P (it->f)
10301 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10302 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10303 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10304 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10305 {
10306 bool at_eob_p = false;
10307
10308 if ((at_eob_p = !get_next_display_element (it))
10309 || BUFFER_POS_REACHED_P ()
10310
10311
10312
10313
10314 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10315 && !saw_smaller_pos
10316 && IT_CHARPOS (*it) > to_charpos))
10317 {
10318 if (it->bidi_p
10319 && !BUFFER_POS_REACHED_P ()
10320 && !at_eob_p && closest_pos < ZV)
10321 {
10322 RESTORE_IT (it, &ppos_it, ppos_data);
10323 if (closest_pos != to_charpos)
10324 move_it_in_display_line_to (it, closest_pos, -1,
10325 MOVE_TO_POS);
10326 }
10327 result = MOVE_POS_MATCH_OR_ZV;
10328 break;
10329 }
10330 if (ITERATOR_AT_END_OF_LINE_P (it))
10331 {
10332 result = MOVE_NEWLINE_OR_CR;
10333 break;
10334 }
10335 }
10336 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10337 && !saw_smaller_pos
10338 && IT_CHARPOS (*it) > to_charpos)
10339 {
10340 if (closest_pos < ZV)
10341 {
10342 RESTORE_IT (it, &ppos_it, ppos_data);
10343 if (closest_pos != to_charpos)
10344 move_it_in_display_line_to (it, closest_pos, -1,
10345 MOVE_TO_POS);
10346 }
10347 result = MOVE_POS_MATCH_OR_ZV;
10348 break;
10349 }
10350 result = MOVE_LINE_TRUNCATED;
10351 break;
10352 }
10353 #undef IT_RESET_X_ASCENT_DESCENT
10354 }
10355
10356 #undef BUFFER_POS_REACHED_P
10357
10358
10359
10360
10361
10362
10363 if (result == MOVE_LINE_CONTINUED
10364 && it->line_wrap == WORD_WRAP
10365 && wrap_it.sp >= 0
10366 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10367 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10368 RESTORE_IT (it, &wrap_it, wrap_data);
10369 else if (atpos_it.sp >= 0)
10370 RESTORE_IT (it, &atpos_it, atpos_data);
10371 else if (atx_it.sp >= 0)
10372 RESTORE_IT (it, &atx_it, atx_data);
10373
10374 done:
10375
10376 if (atpos_data)
10377 bidi_unshelve_cache (atpos_data, true);
10378 if (atx_data)
10379 bidi_unshelve_cache (atx_data, true);
10380 if (wrap_data)
10381 bidi_unshelve_cache (wrap_data, true);
10382 if (ppos_data)
10383 bidi_unshelve_cache (ppos_data, true);
10384
10385
10386
10387 it->glyph_row = saved_glyph_row;
10388 return result;
10389 }
10390
10391
10392 void
10393 move_it_in_display_line (struct it *it,
10394 ptrdiff_t to_charpos, int to_x,
10395 enum move_operation_enum op)
10396 {
10397 if (it->line_wrap == WORD_WRAP
10398 && (op & MOVE_TO_X))
10399 {
10400 struct it save_it;
10401 void *save_data = NULL;
10402 int skip;
10403
10404 SAVE_IT (save_it, *it, save_data);
10405 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10406
10407
10408
10409
10410 if (skip == MOVE_LINE_CONTINUED)
10411 {
10412 int prev_x = max (it->current_x - 1, 0);
10413 RESTORE_IT (it, &save_it, save_data);
10414 move_it_in_display_line_to
10415 (it, -1, prev_x, MOVE_TO_X);
10416 }
10417 else
10418 bidi_unshelve_cache (save_data, true);
10419 }
10420 else
10421 move_it_in_display_line_to (it, to_charpos, to_x, op);
10422 }
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439 int
10440 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10441 {
10442 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10443 int line_height, line_start_x = 0, reached = 0;
10444 int max_current_x = 0;
10445 void *backup_data = NULL;
10446 ptrdiff_t orig_charpos = -1;
10447 enum it_method orig_method = NUM_IT_METHODS;
10448
10449 for (;;)
10450 {
10451 orig_charpos = IT_CHARPOS (*it);
10452 orig_method = it->method;
10453 if (op & MOVE_TO_VPOS)
10454 {
10455
10456
10457 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10458 {
10459 if (it->vpos == to_vpos)
10460 {
10461 reached = 1;
10462 break;
10463 }
10464 else
10465 skip = move_it_in_display_line_to (it, -1, -1, 0);
10466 }
10467 else
10468 {
10469
10470
10471 if (it->vpos == to_vpos)
10472 {
10473 reached = 2;
10474 break;
10475 }
10476
10477 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10478
10479 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10480 {
10481 reached = 3;
10482 break;
10483 }
10484 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10485 {
10486
10487 skip = move_it_in_display_line_to (it, to_charpos,
10488 -1, MOVE_TO_POS);
10489 if (skip == MOVE_POS_MATCH_OR_ZV)
10490 {
10491 reached = 4;
10492 break;
10493 }
10494 }
10495 }
10496 }
10497 else if (op & MOVE_TO_Y)
10498 {
10499 struct it it_backup;
10500
10501 if (it->line_wrap == WORD_WRAP)
10502 SAVE_IT (it_backup, *it, backup_data);
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516 skip = move_it_in_display_line_to
10517 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10518 (MOVE_TO_X | (op & MOVE_TO_POS)));
10519
10520
10521 if (skip == MOVE_POS_MATCH_OR_ZV)
10522 reached = 5;
10523 else if (skip == MOVE_X_REACHED)
10524 {
10525
10526
10527
10528
10529 line_height = it->max_ascent + it->max_descent;
10530 if (to_y >= it->current_y
10531 && to_y < it->current_y + line_height)
10532 {
10533 reached = 6;
10534 break;
10535 }
10536 SAVE_IT (it_backup, *it, backup_data);
10537 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10538 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10539 op & MOVE_TO_POS);
10540 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10541 line_height = it->max_ascent + it->max_descent;
10542 move_trace ("move_it: line_height = %d\n", line_height);
10543
10544 if (to_y >= it->current_y
10545 && to_y < it->current_y + line_height)
10546 {
10547
10548
10549
10550
10551
10552
10553
10554
10555 int max_ascent = it->max_ascent;
10556 int max_descent = it->max_descent;
10557
10558 RESTORE_IT (it, &it_backup, backup_data);
10559 it->max_ascent = max_ascent;
10560 it->max_descent = max_descent;
10561 reached = 6;
10562 }
10563 else
10564 {
10565 skip = skip2;
10566 if (skip == MOVE_POS_MATCH_OR_ZV)
10567 {
10568 reached = 7;
10569
10570
10571
10572
10573
10574
10575
10576 if (to_charpos > 0
10577 && IT_CHARPOS (*it) != to_charpos
10578 && ((IT_CHARPOS (it_backup) > to_charpos)
10579 == (IT_CHARPOS (*it) > to_charpos)))
10580 {
10581 int max_ascent = it->max_ascent;
10582 int max_descent = it->max_descent;
10583
10584 RESTORE_IT (it, &it_backup, backup_data);
10585 it->max_ascent = max_ascent;
10586 it->max_descent = max_descent;
10587 }
10588 }
10589 }
10590 }
10591 else
10592 {
10593
10594 line_height = it->max_ascent + it->max_descent;
10595 move_trace ("move_it: line_height = %d\n", line_height);
10596
10597 if (to_y >= it->current_y
10598 && to_y < it->current_y + line_height)
10599 {
10600 if (to_y > it->current_y)
10601 max_current_x = max (it->current_x, max_current_x);
10602
10603
10604
10605
10606
10607 if (skip == MOVE_LINE_CONTINUED
10608 && it->line_wrap == WORD_WRAP)
10609 {
10610 int prev_x = max (it->current_x - 1, 0);
10611 RESTORE_IT (it, &it_backup, backup_data);
10612 skip = move_it_in_display_line_to
10613 (it, -1, prev_x, MOVE_TO_X);
10614 }
10615
10616 reached = 6;
10617 }
10618 }
10619
10620 if (reached)
10621 {
10622 max_current_x = max (it->current_x, max_current_x);
10623 break;
10624 }
10625 }
10626 else if (BUFFERP (it->object)
10627 && (it->method == GET_FROM_BUFFER
10628 || it->method == GET_FROM_STRETCH)
10629 && IT_CHARPOS (*it) >= to_charpos
10630
10631
10632
10633
10634
10635 && !(it->bidi_p
10636 && it->bidi_it.scan_dir == -1))
10637 skip = MOVE_POS_MATCH_OR_ZV;
10638 else
10639 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10640
10641 switch (skip)
10642 {
10643 case MOVE_POS_MATCH_OR_ZV:
10644 max_current_x = max (it->current_x, max_current_x);
10645 reached = 8;
10646 goto out;
10647
10648 case MOVE_NEWLINE_OR_CR:
10649 max_current_x = max (it->current_x, max_current_x);
10650 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10651 it->override_ascent = -1;
10652 set_iterator_to_next (it, true);
10653 it->continuation_lines_width = 0;
10654 break;
10655
10656 case MOVE_LINE_TRUNCATED:
10657 max_current_x = it->last_visible_x;
10658 it->continuation_lines_width = 0;
10659 reseat_at_next_visible_line_start (it, false);
10660 if ((op & MOVE_TO_POS) != 0
10661 && (IT_CHARPOS (*it) > to_charpos
10662 || (IT_CHARPOS (*it) == to_charpos
10663
10664
10665 && to_charpos == ZV
10666 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10667
10668
10669
10670 && (it->sp == 0
10671 || (STRINGP (it->string)
10672 && (it->current.overlay_string_index < 0
10673 || (it->current.overlay_string_index >= 0
10674 && it->current.overlay_string_index
10675 >= it->n_overlay_strings - 1))
10676 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10677 {
10678 reached = 9;
10679 goto out;
10680 }
10681 break;
10682
10683 case MOVE_LINE_CONTINUED:
10684 max_current_x = it->last_visible_x;
10685
10686
10687
10688
10689 if (it->c == '\t')
10690 {
10691 it->continuation_lines_width += it->last_visible_x;
10692
10693
10694
10695 if (it->current_x != it->last_visible_x
10696 && (op & MOVE_TO_VPOS)
10697 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10698 {
10699 line_start_x = it->current_x + it->pixel_width
10700 - it->last_visible_x;
10701 if (FRAME_WINDOW_P (it->f))
10702 {
10703 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10704 struct font *face_font = face->font;
10705
10706
10707
10708
10709
10710
10711
10712 eassert (face_font);
10713 if (face_font)
10714 {
10715 if (line_start_x < face_font->space_width)
10716 line_start_x
10717 += it->tab_width * face_font->space_width;
10718 }
10719 }
10720 set_iterator_to_next (it, false);
10721 }
10722 }
10723 else
10724 {
10725
10726
10727
10728
10729
10730
10731
10732
10733 if (IT_CHARPOS (*it) == orig_charpos
10734 && it->method == orig_method
10735 && orig_method == GET_FROM_BUFFER)
10736 set_iterator_to_next (it, false);
10737 it->continuation_lines_width += it->current_x;
10738 }
10739 break;
10740
10741 default:
10742 emacs_abort ();
10743 }
10744
10745
10746 it->current_x = line_start_x;
10747 line_start_x = 0;
10748 it->hpos = 0;
10749 it->line_number_produced_p = false;
10750 it->current_y += it->max_ascent + it->max_descent;
10751 ++it->vpos;
10752 last_height = it->max_ascent + it->max_descent;
10753 it->max_ascent = it->max_descent = 0;
10754 }
10755
10756 out:
10757
10758
10759
10760
10761
10762
10763 if (!FRAME_WINDOW_P (it->f)
10764 && op & MOVE_TO_POS
10765 && IT_CHARPOS (*it) == to_charpos
10766 && it->what == IT_CHARACTER
10767 && it->nglyphs > 1
10768 && it->line_wrap == WINDOW_WRAP
10769 && it->current_x == it->last_visible_x - 1
10770 && it->c != '\n'
10771 && it->c != '\t'
10772 && it->w->window_end_valid
10773 && it->vpos < it->w->window_end_vpos)
10774 {
10775 it->continuation_lines_width += it->current_x;
10776 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10777 it->current_y += it->max_ascent + it->max_descent;
10778 ++it->vpos;
10779 last_height = it->max_ascent + it->max_descent;
10780 }
10781
10782 if (backup_data)
10783 bidi_unshelve_cache (backup_data, true);
10784
10785 move_trace ("move_it_to: reached %d\n", reached);
10786
10787 return max_current_x;
10788 }
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800 void
10801 move_it_vertically_backward (struct it *it, int dy)
10802 {
10803 int nlines, h;
10804 struct it it2, it3;
10805 void *it2data = NULL, *it3data = NULL;
10806 ptrdiff_t start_pos;
10807 int nchars_per_row
10808 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10809 ptrdiff_t pos_limit;
10810
10811 move_further_back:
10812 eassert (dy >= 0);
10813
10814 start_pos = IT_CHARPOS (*it);
10815
10816
10817 nlines = max (1, dy / default_line_pixel_height (it->w));
10818 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10819 pos_limit = BEGV;
10820 else
10821 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10822
10823
10824
10825
10826 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10827 back_to_previous_visible_line_start (it);
10828
10829
10830
10831
10832
10833 reseat_1 (it, it->current.pos, true);
10834
10835
10836 it->current_x = it->hpos = 0;
10837
10838 it->continuation_lines_width = 0;
10839
10840
10841
10842
10843
10844 SAVE_IT (it2, *it, it2data);
10845 it2.max_ascent = it2.max_descent = 0;
10846 do
10847 {
10848 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10849 MOVE_TO_POS | MOVE_TO_VPOS);
10850 }
10851 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10852
10853
10854
10855
10856
10857
10858 || (it2.method == GET_FROM_STRING
10859 && IT_CHARPOS (it2) == start_pos
10860 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10861 eassert (IT_CHARPOS (*it) >= BEGV);
10862 SAVE_IT (it3, it2, it3data);
10863
10864 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10865 eassert (IT_CHARPOS (*it) >= BEGV);
10866
10867
10868 h = it2.current_y - it->current_y;
10869
10870 nlines = it2.vpos - it->vpos;
10871
10872
10873
10874 it->vpos -= nlines;
10875 it->current_y -= h;
10876
10877 if (dy == 0)
10878 {
10879
10880
10881
10882 RESTORE_IT (it, it, it2data);
10883 if (nlines > 0)
10884 move_it_by_lines (it, nlines);
10885
10886
10887
10888
10889
10890
10891 if (it->bidi_p
10892 && !it->continuation_lines_width
10893 && !STRINGP (it->string)
10894 && IT_CHARPOS (*it) > BEGV
10895 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10896 {
10897 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10898
10899 dec_both (&cp, &bp);
10900 SET_WITH_NARROWED_BEGV (it, cp,
10901 find_newline_no_quit (cp, bp, -1, NULL),
10902 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10903 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10904 }
10905 bidi_unshelve_cache (it3data, true);
10906 }
10907 else
10908 {
10909
10910
10911 int target_y = it->current_y + h - dy;
10912 int y0 = it3.current_y;
10913 int y1;
10914 int line_height;
10915
10916 RESTORE_IT (&it3, &it3, it3data);
10917 y1 = line_bottom_y (&it3);
10918 line_height = y1 - y0;
10919 RESTORE_IT (it, it, it2data);
10920
10921
10922 if (target_y < it->current_y
10923
10924
10925
10926
10927 && (it->current_y - target_y
10928 > min (window_box_height (it->w), line_height * 2 / 3))
10929 && IT_CHARPOS (*it) > BEGV)
10930 {
10931 move_trace (" not far enough -> move_vert %d\n",
10932 target_y - it->current_y);
10933 dy = it->current_y - target_y;
10934 goto move_further_back;
10935 }
10936 else if (target_y >= it->current_y + line_height
10937 && IT_CHARPOS (*it) < ZV)
10938 {
10939
10940
10941
10942
10943
10944
10945
10946
10947 if (!FRAME_WINDOW_P (it->f))
10948 move_it_vertically (it, target_y - it->current_y);
10949 else
10950 {
10951 struct text_pos last_pos;
10952 int last_y, last_vpos;
10953 do
10954 {
10955 last_pos = it->current.pos;
10956 last_y = it->current_y;
10957 last_vpos = it->vpos;
10958 move_it_by_lines (it, 1);
10959 }
10960 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10961 if (it->current_y > target_y)
10962 {
10963 reseat (it, last_pos, true);
10964 it->current_y = last_y;
10965 it->vpos = last_vpos;
10966 }
10967 }
10968 }
10969 }
10970 }
10971
10972
10973
10974
10975
10976
10977 void
10978 move_it_vertically (struct it *it, int dy)
10979 {
10980 if (dy <= 0)
10981 move_it_vertically_backward (it, -dy);
10982 else
10983 {
10984 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10985 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10986 MOVE_TO_POS | MOVE_TO_Y);
10987 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10988
10989
10990
10991 if (IT_CHARPOS (*it) == ZV
10992 && ZV > BEGV
10993 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10994 move_it_by_lines (it, 0);
10995 }
10996 }
10997
10998
10999
11000
11001 void
11002 move_it_past_eol (struct it *it)
11003 {
11004 enum move_it_result rc;
11005
11006 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
11007 if (rc == MOVE_NEWLINE_OR_CR)
11008 set_iterator_to_next (it, false);
11009 }
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020 void
11021 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11022 {
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040 if (dvpos == 0)
11041 {
11042
11043 move_it_vertically_backward (it, 0);
11044
11045 last_height = 0;
11046 }
11047 else if (dvpos > 0)
11048 {
11049 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11050 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11051 {
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11063 -1, -1, -1, MOVE_TO_POS);
11064 }
11065 }
11066 else
11067 {
11068 struct it it2;
11069 void *it2data = NULL;
11070 ptrdiff_t start_charpos, orig_charpos, i;
11071 int nchars_per_row
11072 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11073 bool hit_pos_limit = false;
11074 ptrdiff_t pos_limit;
11075
11076
11077
11078
11079 dvpos += it->vpos;
11080 orig_charpos = IT_CHARPOS (*it);
11081 move_it_vertically_backward (it, 0);
11082 dvpos -= it->vpos;
11083
11084
11085
11086 start_charpos = IT_CHARPOS (*it);
11087 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11088 pos_limit = BEGV;
11089 else
11090 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11091
11092 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11093 back_to_previous_visible_line_start (it);
11094 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11095 hit_pos_limit = true;
11096 reseat (it, it->current.pos, true);
11097
11098
11099 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11100 {
11101
11102 dvpos += it->vpos;
11103 move_it_vertically_backward (it, 0);
11104 dvpos -= it->vpos;
11105 if (IT_POS_VALID_AFTER_MOVE_P (it))
11106 break;
11107
11108
11109 back_to_previous_visible_line_start (it);
11110 reseat (it, it->current.pos, true);
11111 dvpos--;
11112 }
11113
11114 it->current_x = it->hpos = 0;
11115
11116
11117
11118 SAVE_IT (it2, *it, it2data);
11119 it2.vpos = it2.current_y = 0;
11120 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11121 it->vpos -= it2.vpos;
11122 it->current_y -= it2.current_y;
11123 it->current_x = it->hpos = 0;
11124
11125
11126 if (it2.vpos > -dvpos)
11127 {
11128 int delta = it2.vpos + dvpos;
11129
11130 RESTORE_IT (&it2, &it2, it2data);
11131 SAVE_IT (it2, *it, it2data);
11132 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11133
11134
11135 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11136 RESTORE_IT (it, &it2, it2data);
11137 else
11138 bidi_unshelve_cache (it2data, true);
11139 }
11140 else if (hit_pos_limit && pos_limit > BEGV
11141 && dvpos < 0 && it2.vpos < -dvpos)
11142 {
11143
11144
11145
11146
11147
11148
11149
11150
11151 dvpos += it2.vpos;
11152 RESTORE_IT (it, it, it2data);
11153 for (i = -dvpos; i > 0; --i)
11154 {
11155 back_to_previous_visible_line_start (it);
11156 it->vpos--;
11157 }
11158 reseat_1 (it, it->current.pos, true);
11159 }
11160 else
11161 RESTORE_IT (it, it, it2data);
11162 }
11163 }
11164
11165 int
11166 partial_line_height (struct it *it_origin)
11167 {
11168
11169
11170
11171
11172
11173 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11174 && it_origin->line_wrap == TRUNCATE)
11175 return 0;
11176
11177 int partial_height;
11178 void *it_data = NULL;
11179 struct it it;
11180 SAVE_IT (it, *it_origin, it_data);
11181 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11182 MOVE_TO_POS | MOVE_TO_Y);
11183 if (it.what == IT_EOB)
11184 {
11185 int vis_height = it.last_visible_y - it.current_y;
11186 int height = it.ascent + it.descent;
11187 partial_height = (vis_height < height) ? vis_height : 0;
11188 }
11189 else
11190 {
11191 int last_line_y = it.current_y;
11192 move_it_by_lines (&it, 1);
11193 partial_height = (it.current_y > it.last_visible_y)
11194 ? it.last_visible_y - last_line_y : 0;
11195 }
11196 RESTORE_IT (&it, &it, it_data);
11197 return partial_height;
11198 }
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211 static enum move_it_result
11212 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11213 {
11214 ptrdiff_t nl_bytepos;
11215 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11216 1, &nl_bytepos);
11217 struct text_pos new_pos;
11218 enum move_it_result move_result;
11219
11220 if (nl_pos - IT_CHARPOS (*it) > nchars)
11221 {
11222 SET_TEXT_POS (new_pos,
11223 IT_CHARPOS (*it) + nchars,
11224 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11225 move_result = MOVE_X_REACHED;
11226 }
11227 else
11228 {
11229 if (nl_bytepos < ZV_BYTE
11230 || (nl_bytepos > BEGV_BYTE
11231 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11232 {
11233 nl_pos--;
11234 nl_bytepos--;
11235 move_result = MOVE_NEWLINE_OR_CR;
11236 }
11237 else
11238 move_result = MOVE_POS_MATCH_OR_ZV;
11239 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11240 }
11241 reseat (it, new_pos, false);
11242 return move_result;
11243 }
11244
11245
11246
11247 bool
11248 in_display_vector_p (struct it *it)
11249 {
11250 return (it->method == GET_FROM_DISPLAY_VECTOR
11251 && it->current.dpvec_index > 0
11252 && it->dpvec + it->current.dpvec_index != it->dpend);
11253 }
11254
11255
11256
11257
11258
11259 static Lisp_Object
11260 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11261 Lisp_Object x_limit, Lisp_Object y_limit,
11262 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11263 {
11264 struct window *w = decode_live_window (window);
11265 struct it it;
11266 ptrdiff_t start, end, bpos;
11267 struct text_pos startp;
11268 void *itdata = NULL;
11269 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11270
11271 if (NILP (from))
11272 {
11273 start = BEGV;
11274 bpos = BEGV_BYTE;
11275 }
11276 else if (EQ (from, Qt))
11277 {
11278 start = BEGV;
11279 bpos = BEGV_BYTE;
11280 while (bpos < ZV_BYTE)
11281 {
11282 c = FETCH_BYTE (bpos);
11283 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11284 break;
11285 inc_both (&start, &bpos);
11286 }
11287 while (bpos > BEGV_BYTE)
11288 {
11289 dec_both (&start, &bpos);
11290 c = FETCH_BYTE (bpos);
11291 if (!(c == ' ' || c == '\t'))
11292 break;
11293 }
11294 }
11295 else if (CONSP (from))
11296 {
11297 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11298 bpos = CHAR_TO_BYTE (start);
11299 CHECK_FIXNUM (XCDR (from));
11300 vertical_offset = XFIXNUM (XCDR (from));
11301 }
11302 else
11303 {
11304 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11305 bpos = CHAR_TO_BYTE (start);
11306 }
11307
11308 SET_TEXT_POS (startp, start, bpos);
11309
11310 if (NILP (to))
11311 end = ZV;
11312 else if (EQ (to, Qt))
11313 {
11314 end = ZV;
11315 bpos = ZV_BYTE;
11316 while (bpos > BEGV_BYTE)
11317 {
11318 dec_both (&end, &bpos);
11319 c = FETCH_BYTE (bpos);
11320 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11321 {
11322 inc_both (&end, &bpos);
11323 break;
11324 }
11325 }
11326 while (bpos < ZV_BYTE)
11327 {
11328 c = fetch_char_advance (&end, &bpos);
11329 if (!(c == ' ' || c == '\t'))
11330 break;
11331 }
11332 }
11333 else
11334 end = clip_to_bounds (start, fix_position (to), ZV);
11335
11336 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11337 max_x = XFIXNUM (x_limit);
11338 else if (!NILP (x_limit))
11339 max_x = INT_MAX;
11340
11341 if (NILP (y_limit))
11342 max_y = INT_MAX;
11343 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11344 max_y = XFIXNUM (y_limit);
11345
11346 itdata = bidi_shelve_cache ();
11347
11348 start_display (&it, w, startp);
11349
11350 int start_y = it.current_y;
11351
11352
11353
11354
11355
11356
11357
11358 it.bidi_p = false;
11359
11360 int start_x;
11361 if (vertical_offset != 0)
11362 {
11363 int last_y;
11364 it.current_y = 0;
11365
11366 move_it_by_lines (&it, 0);
11367
11368
11369
11370
11371
11372 if (vertical_offset < 0)
11373 {
11374 while (it.current_y > vertical_offset)
11375 {
11376 last_y = it.current_y;
11377 move_it_vertically_backward (&it,
11378 (abs (vertical_offset)
11379 + it.current_y));
11380
11381 if (it.current_y == last_y)
11382 break;
11383 }
11384 }
11385 else
11386 {
11387 move_it_vertically (&it, vertical_offset);
11388 }
11389
11390 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11391 + WINDOW_HEADER_LINE_HEIGHT (w));
11392 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11393 start_y = it.current_y;
11394 start_x = it.current_x;
11395 }
11396 else
11397 {
11398
11399
11400
11401 reseat_at_previous_visible_line_start (&it);
11402 it.current_x = it.hpos = 0;
11403 if (IT_CHARPOS (it) != start)
11404 {
11405 void *it1data = NULL;
11406 struct it it1;
11407
11408 SAVE_IT (it1, it, it1data);
11409 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11410
11411
11412
11413
11414
11415 if (IT_CHARPOS (it) > start && start > BEGV)
11416 {
11417 ptrdiff_t it1pos = IT_CHARPOS (it1);
11418 int it1_x = it1.current_x;
11419
11420 RESTORE_IT (&it, &it1, it1data);
11421
11422
11423
11424
11425
11426 if (start - 1 > it1pos)
11427 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11428 else
11429 move_it_in_display_line (&it, start, it1_x + 1,
11430 MOVE_TO_POS | MOVE_TO_X);
11431 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11432 start_x = it.current_x;
11433
11434
11435
11436 if (IT_CHARPOS (it) == start - 1)
11437 start_x += it.pixel_width;
11438 }
11439 else
11440 {
11441 start_x = it.current_x;
11442 bidi_unshelve_cache (it1data, true);
11443 }
11444 }
11445 else
11446 start_x = it.current_x;
11447 }
11448
11449
11450 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11451 int to_x = -1;
11452 it.current_y = start_y;
11453
11454
11455 if (FETCH_BYTE (start) == '\n')
11456 it.current_x = 0;
11457 if (!NILP (x_limit))
11458 {
11459 it.last_visible_x = max_x;
11460
11461
11462
11463 move_op |= MOVE_TO_X;
11464 to_x = INT_MAX;
11465 }
11466
11467 void *it2data = NULL;
11468 struct it it2;
11469 SAVE_IT (it2, it, it2data);
11470
11471 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11472
11473
11474
11475
11476
11477 if (IT_CHARPOS (it) > end)
11478 {
11479 end--;
11480 RESTORE_IT (&it, &it2, it2data);
11481 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11482
11483
11484
11485 if (IT_CHARPOS (it) == end)
11486 {
11487 x += it.pixel_width;
11488
11489
11490 if (!NILP (ignore_line_at_end))
11491 doff = (max (it.max_ascent, it.ascent)
11492 + max (it.max_descent, it.descent));
11493 else
11494 {
11495 it.max_ascent = max (it.max_ascent, it.ascent);
11496 it.max_descent = max (it.max_descent, it.descent);
11497 }
11498 }
11499 }
11500 else
11501 bidi_unshelve_cache (it2data, true);
11502
11503 if (!NILP (x_limit))
11504 {
11505
11506 if (x > max_x)
11507 x = max_x;
11508 }
11509
11510
11511
11512
11513 if (it.current_y > start_y)
11514 start_x = 0;
11515
11516
11517
11518 if (!NILP (ignore_line_at_end))
11519 y = (it.current_y + doff
11520 - WINDOW_TAB_LINE_HEIGHT (w)
11521 - WINDOW_HEADER_LINE_HEIGHT (w));
11522 else
11523 y = (it.current_y + it.max_ascent + it.max_descent + doff
11524 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11525
11526
11527 if (y > max_y)
11528 y = max_y;
11529
11530 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11531 && window_wants_tab_line (w))
11532
11533 {
11534 Lisp_Object window_tab_line_format
11535 = window_parameter (w, Qtab_line_format);
11536
11537 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11538 NILP (window_tab_line_format)
11539 ? BVAR (current_buffer, tab_line_format)
11540 : window_tab_line_format);
11541 }
11542
11543 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11544 && window_wants_header_line (w))
11545 {
11546 Lisp_Object window_header_line_format
11547 = window_parameter (w, Qheader_line_format);
11548
11549 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11550 NILP (window_header_line_format)
11551 ? BVAR (current_buffer, header_line_format)
11552 : window_header_line_format);
11553 }
11554
11555 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11556 && window_wants_mode_line (w))
11557 {
11558 Lisp_Object window_mode_line_format
11559 = window_parameter (w, Qmode_line_format);
11560
11561 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11562 NILP (window_mode_line_format)
11563 ? BVAR (current_buffer, mode_line_format)
11564 : window_mode_line_format);
11565 }
11566
11567 bidi_unshelve_cache (itdata, false);
11568
11569 return (!vertical_offset
11570 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11571 : list3i (x - start_x, y, start));
11572 }
11573
11574 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11575 doc:
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630 )
11631 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11632 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11633 {
11634 struct window *w = decode_live_window (window);
11635 struct buffer *b = XBUFFER (w->contents);
11636 struct buffer *old_b = NULL;
11637 Lisp_Object value;
11638
11639 if (b != current_buffer)
11640 {
11641 old_b = current_buffer;
11642 set_buffer_internal_1 (b);
11643 }
11644
11645 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11646 ignore_line_at_end);
11647
11648 if (old_b)
11649 set_buffer_internal_1 (old_b);
11650
11651 return value;
11652 }
11653
11654 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11655 doc:
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668 )
11669 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11670 Lisp_Object y_limit)
11671 {
11672 struct window *w = decode_live_window (window);
11673 struct buffer *b = (NILP (buffer_or_name)
11674 ? current_buffer
11675 : XBUFFER (Fget_buffer (buffer_or_name)));
11676 Lisp_Object buffer, value;
11677 specpdl_ref count = SPECPDL_INDEX ();
11678
11679 XSETBUFFER (buffer, b);
11680
11681
11682
11683
11684 record_unwind_protect (unwind_with_echo_area_buffer,
11685 with_echo_area_buffer_unwind_data (w));
11686
11687 set_buffer_internal_1 (b);
11688
11689 ptrdiff_t base_line_pos = w->base_line_pos;
11690 int end_valid = w->window_end_valid;
11691 if (!EQ (buffer, w->contents))
11692 {
11693 wset_buffer (w, buffer);
11694 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11695 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11696 }
11697
11698 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11699 Qnil);
11700
11701 unbind_to (count, Qnil);
11702
11703
11704
11705 w->base_line_pos = base_line_pos;
11706 w->window_end_valid = end_valid;
11707
11708 return value;
11709 }
11710
11711
11712 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11713 Sdisplay__line_is_continued_p, 0, 0, 0,
11714 doc: )
11715 (void)
11716 {
11717 struct buffer *oldb = current_buffer;
11718 struct window *w = XWINDOW (selected_window);
11719 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11720
11721 set_buffer_internal_1 (XBUFFER (w->contents));
11722
11723 if (PT < ZV)
11724 {
11725 struct text_pos startpos;
11726 struct it it;
11727 void *itdata;
11728
11729
11730 Lisp_Object opoint = Fpoint_marker ();
11731
11732
11733
11734 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11735 SET_TEXT_POS (startpos, PT, PT_BYTE);
11736 itdata = bidi_shelve_cache ();
11737 start_display (&it, w, startpos);
11738
11739 if (it.line_wrap != TRUNCATE)
11740 {
11741 it.glyph_row = NULL;
11742 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11743 }
11744 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11745 bidi_unshelve_cache (itdata, false);
11746 }
11747 set_buffer_internal_1 (oldb);
11748
11749 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11750 }
11751
11752
11753
11754
11755
11756
11757
11758
11759 static ptrdiff_t
11760 format_nargs (char const *format)
11761 {
11762 ptrdiff_t nargs = 0;
11763 for (char const *p = format; (p = strchr (p, '%')); p++)
11764 if (p[1] == '%')
11765 p++;
11766 else
11767 nargs++;
11768 return nargs;
11769 }
11770
11771
11772
11773
11774 void
11775 add_to_log (const char *format, ...)
11776 {
11777 va_list ap;
11778 va_start (ap, format);
11779 vadd_to_log (format, ap);
11780 va_end (ap);
11781 }
11782
11783 void
11784 vadd_to_log (char const *format, va_list ap)
11785 {
11786 ptrdiff_t form_nargs = format_nargs (format);
11787 ptrdiff_t nargs = 1 + form_nargs;
11788 Lisp_Object args[10];
11789 eassert (nargs <= ARRAYELTS (args));
11790 AUTO_STRING (args0, format);
11791 args[0] = args0;
11792 for (ptrdiff_t i = 1; i <= nargs; i++)
11793 args[i] = va_arg (ap, Lisp_Object);
11794 Lisp_Object msg = Qnil;
11795 msg = Fformat_message (nargs, args);
11796
11797 ptrdiff_t len = SBYTES (msg) + 1;
11798 USE_SAFE_ALLOCA;
11799 char *buffer = SAFE_ALLOCA (len);
11800 memcpy (buffer, SDATA (msg), len);
11801
11802 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11803 SAFE_FREE ();
11804 }
11805
11806
11807
11808
11809 void
11810 message_log_maybe_newline (void)
11811 {
11812 if (message_log_need_newline)
11813 message_dolog ("", 0, true, false);
11814 }
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826 void
11827 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11828 {
11829 const unsigned char *msg = (const unsigned char *) m;
11830
11831 if (!NILP (Vmemory_full))
11832 return;
11833
11834 if (!NILP (Vmessage_log_max))
11835 {
11836 struct buffer *oldbuf;
11837 Lisp_Object oldpoint, oldbegv, oldzv;
11838 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11839 ptrdiff_t point_at_end = 0;
11840 ptrdiff_t zv_at_end = 0;
11841 Lisp_Object old_deactivate_mark;
11842
11843 old_deactivate_mark = Vdeactivate_mark;
11844 oldbuf = current_buffer;
11845
11846
11847
11848 if (! STRINGP (Vmessages_buffer_name))
11849 Vmessages_buffer_name = build_string ("*Messages*");
11850
11851
11852 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11853 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11854 if (newbuffer
11855 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11856 call0 (intern ("messages-buffer-mode"));
11857
11858 bset_undo_list (current_buffer, Qt);
11859 bset_cache_long_scans (current_buffer, Qnil);
11860
11861 oldpoint = message_dolog_marker1;
11862 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11863 oldbegv = message_dolog_marker2;
11864 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11865 oldzv = message_dolog_marker3;
11866 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11867
11868 if (PT == Z)
11869 point_at_end = 1;
11870 if (ZV == Z)
11871 zv_at_end = 1;
11872
11873 BEGV = BEG;
11874 BEGV_BYTE = BEG_BYTE;
11875 ZV = Z;
11876 ZV_BYTE = Z_BYTE;
11877 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11878
11879
11880
11881 if (multibyte
11882 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11883 {
11884
11885
11886 for (ptrdiff_t i = 0; i < nbytes; )
11887 {
11888 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11889 char work = CHAR_TO_BYTE8 (c);
11890 insert_1_both (&work, 1, 1, true, false, false);
11891 i += char_bytes;
11892 }
11893 }
11894 else if (! multibyte
11895 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11896 {
11897
11898
11899 for (ptrdiff_t i = 0; i < nbytes; i++)
11900 {
11901 int c = make_char_multibyte (msg[i]);
11902 unsigned char str[MAX_MULTIBYTE_LENGTH];
11903 int char_bytes = CHAR_STRING (c, str);
11904 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11905 }
11906 }
11907 else if (nbytes)
11908 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11909 true, false, false);
11910
11911 if (nlflag)
11912 {
11913 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11914 intmax_t dups;
11915
11916
11917
11918
11919
11920 specpdl_ref count = SPECPDL_INDEX ();
11921 specbind (Qinhibit_modification_hooks, Qt);
11922
11923 insert_1_both ("\n", 1, 1, true, false, false);
11924
11925 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11926 this_bol = PT;
11927 this_bol_byte = PT_BYTE;
11928
11929
11930
11931 if (this_bol > BEG)
11932 {
11933 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11934 prev_bol = PT;
11935 prev_bol_byte = PT_BYTE;
11936
11937 dups = message_log_check_duplicate (prev_bol_byte,
11938 this_bol_byte);
11939 if (dups)
11940 {
11941 del_range_both (prev_bol, prev_bol_byte,
11942 this_bol, this_bol_byte, false);
11943 if (dups > 1)
11944 {
11945 char dupstr[sizeof " [ times]"
11946 + INT_STRLEN_BOUND (dups)];
11947
11948
11949
11950 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11951 dups);
11952 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11953 insert_1_both (dupstr, duplen, duplen,
11954 true, false, true);
11955 }
11956 }
11957 }
11958
11959
11960
11961
11962
11963 if (FIXNATP (Vmessage_log_max))
11964 {
11965 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11966 -XFIXNAT (Vmessage_log_max) - 1, false);
11967 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11968 }
11969
11970 unbind_to (count, Qnil);
11971 }
11972 BEGV = marker_position (oldbegv);
11973 BEGV_BYTE = marker_byte_position (oldbegv);
11974
11975 if (zv_at_end)
11976 {
11977 ZV = Z;
11978 ZV_BYTE = Z_BYTE;
11979 }
11980 else
11981 {
11982 ZV = marker_position (oldzv);
11983 ZV_BYTE = marker_byte_position (oldzv);
11984 }
11985
11986 if (point_at_end)
11987 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11988 else
11989
11990
11991 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11992 marker_byte_position (oldpoint));
11993
11994 unchain_marker (XMARKER (oldpoint));
11995 unchain_marker (XMARKER (oldbegv));
11996 unchain_marker (XMARKER (oldzv));
11997
11998
11999
12000
12001
12002
12003
12004 windows_or_buffers_changed = old_windows_or_buffers_changed;
12005 bset_redisplay (current_buffer);
12006
12007 set_buffer_internal (oldbuf);
12008
12009 message_log_need_newline = !nlflag;
12010 Vdeactivate_mark = old_deactivate_mark;
12011 }
12012 }
12013
12014
12015
12016
12017
12018
12019
12020
12021 static intmax_t
12022 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12023 {
12024 ptrdiff_t i;
12025 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
12026 bool seen_dots = false;
12027 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
12028 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
12029
12030 for (i = 0; i < len; i++)
12031 {
12032 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
12033 seen_dots = true;
12034 if (p1[i] != p2[i])
12035 return seen_dots;
12036 }
12037 p1 += len;
12038 if (*p1 == '\n')
12039 return 2;
12040 if (*p1++ == ' ' && *p1++ == '[')
12041 {
12042 char *pend;
12043 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12044 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12045 return n + 1;
12046 }
12047 return 0;
12048 }
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058 void
12059 message3 (Lisp_Object m)
12060 {
12061 clear_message (true, true);
12062 cancel_echoing ();
12063
12064
12065 message_log_maybe_newline ();
12066 if (STRINGP (m))
12067 {
12068 ptrdiff_t nbytes = SBYTES (m);
12069 bool multibyte = STRING_MULTIBYTE (m);
12070 char *buffer;
12071 USE_SAFE_ALLOCA;
12072 SAFE_ALLOCA_STRING (buffer, m);
12073 message_dolog (buffer, nbytes, true, multibyte);
12074 SAFE_FREE ();
12075 }
12076 if (! inhibit_message)
12077 message3_nolog (m);
12078 }
12079
12080
12081
12082 static void
12083 message_to_stderr (Lisp_Object m)
12084 {
12085 if (noninteractive_need_newline)
12086 {
12087 noninteractive_need_newline = false;
12088 errputc ('\n');
12089 }
12090 if (STRINGP (m))
12091 {
12092 Lisp_Object coding_system = Vlocale_coding_system;
12093 Lisp_Object s;
12094
12095 if (!NILP (Vcoding_system_for_write))
12096 coding_system = Vcoding_system_for_write;
12097 if (!NILP (coding_system))
12098 s = code_convert_string_norecord (m, coding_system, true);
12099 else
12100 s = m;
12101
12102 errwrite (SDATA (s), SBYTES (s));
12103 }
12104 if (STRINGP (m) || !cursor_in_echo_area)
12105 errputc ('\n');
12106 }
12107
12108
12109
12110
12111
12112
12113 void
12114 message3_nolog (Lisp_Object m)
12115 {
12116 struct frame *sf = SELECTED_FRAME ();
12117
12118 if (FRAME_INITIAL_P (sf))
12119 message_to_stderr (m);
12120
12121
12122
12123 else if (INTERACTIVE && sf->glyphs_initialized_p)
12124 {
12125
12126
12127 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12128 Lisp_Object frame = XWINDOW (mini_window)->frame;
12129 struct frame *f = XFRAME (frame);
12130
12131 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12132 Fmake_frame_visible (frame);
12133
12134 if (STRINGP (m) && SCHARS (m) > 0)
12135 {
12136 set_message (m);
12137 if (minibuffer_auto_raise)
12138 Fraise_frame (frame);
12139
12140
12141 echo_message_buffer = Qnil;
12142 }
12143 else
12144 clear_message (true, true);
12145
12146 do_pending_window_change (false);
12147 echo_area_display (true);
12148 do_pending_window_change (false);
12149 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12150 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12151 }
12152 }
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163 void
12164 message1 (const char *m)
12165 {
12166 message3 (m ? build_unibyte_string (m) : Qnil);
12167 }
12168
12169
12170
12171
12172 void
12173 message1_nolog (const char *m)
12174 {
12175 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12176 }
12177
12178
12179
12180
12181 void
12182 message_with_string (const char *m, Lisp_Object string, bool log)
12183 {
12184 CHECK_STRING (string);
12185
12186 bool need_message;
12187 if (noninteractive)
12188 need_message = !!m;
12189 else if (!INTERACTIVE)
12190 need_message = false;
12191 else
12192 {
12193
12194
12195
12196 Lisp_Object mini_window;
12197 struct frame *f, *sf = SELECTED_FRAME ();
12198
12199
12200
12201 mini_window = FRAME_MINIBUF_WINDOW (sf);
12202 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12203
12204
12205
12206
12207 need_message = f->glyphs_initialized_p;
12208 }
12209
12210 if (need_message)
12211 {
12212 AUTO_STRING (fmt, m);
12213 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12214
12215 if (noninteractive)
12216 message_to_stderr (msg);
12217 else
12218 {
12219 if (log)
12220 message3 (msg);
12221 else
12222 message3_nolog (msg);
12223
12224
12225
12226 message_buf_print = false;
12227 }
12228 }
12229 }
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12243 vmessage (const char *m, va_list ap)
12244 {
12245 if (noninteractive)
12246 {
12247 if (m)
12248 {
12249 if (noninteractive_need_newline)
12250 putc ('\n', stderr);
12251 noninteractive_need_newline = false;
12252 vfprintf (stderr, m, ap);
12253 if (!cursor_in_echo_area)
12254 putc ('\n', stderr);
12255 fflush (stderr);
12256 }
12257 }
12258 else if (INTERACTIVE)
12259 {
12260
12261
12262
12263 Lisp_Object mini_window;
12264 struct frame *f, *sf = SELECTED_FRAME ();
12265
12266
12267
12268 mini_window = FRAME_MINIBUF_WINDOW (sf);
12269 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12270
12271
12272
12273
12274 if (f->glyphs_initialized_p)
12275 {
12276 if (m)
12277 {
12278 ptrdiff_t len;
12279 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12280 USE_SAFE_ALLOCA;
12281 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12282
12283 len = doprnt (message_buf, maxsize, m, 0, ap);
12284
12285 message3 (make_string (message_buf, len));
12286 SAFE_FREE ();
12287 }
12288 else
12289 message1 (0);
12290
12291
12292
12293 message_buf_print = false;
12294 }
12295 }
12296 }
12297
12298
12299 void
12300 message (const char *m, ...)
12301 {
12302 va_list ap;
12303 va_start (ap, m);
12304 vmessage (m, ap);
12305 va_end (ap);
12306 }
12307
12308
12309
12310
12311
12312
12313 void
12314 update_echo_area (void)
12315 {
12316 if (!NILP (echo_area_buffer[0]))
12317 {
12318 Lisp_Object string;
12319 string = Fcurrent_message ();
12320 message3 (string);
12321 }
12322 }
12323
12324
12325
12326
12327
12328 static void
12329 ensure_echo_area_buffers (void)
12330 {
12331 for (int i = 0; i < 2; i++)
12332 if (!BUFFERP (echo_buffer[i])
12333 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12334 {
12335 Lisp_Object old_buffer = echo_buffer[i];
12336 static char const name_fmt[] = " *Echo Area %d*";
12337 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12338 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12339 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12340 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12341
12342
12343
12344
12345 for (int j = 0; j < 2; j++)
12346 if (EQ (old_buffer, echo_area_buffer[j]))
12347 echo_area_buffer[j] = echo_buffer[i];
12348 }
12349 }
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368 static bool
12369 with_echo_area_buffer (struct window *w, int which,
12370 bool (*fn) (void *, Lisp_Object),
12371 void *a1, Lisp_Object a2)
12372 {
12373 Lisp_Object buffer;
12374 bool this_one, the_other, clear_buffer_p, rc;
12375 specpdl_ref count = SPECPDL_INDEX ();
12376
12377
12378 ensure_echo_area_buffers ();
12379
12380 clear_buffer_p = false;
12381
12382 if (which == 0)
12383 this_one = false, the_other = true;
12384 else if (which > 0)
12385 this_one = true, the_other = false;
12386 else
12387 {
12388 this_one = false, the_other = true;
12389 clear_buffer_p = true;
12390
12391
12392
12393 if (!NILP (echo_area_buffer[this_one])
12394 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12395 echo_area_buffer[this_one] = Qnil;
12396 }
12397
12398
12399
12400 if (NILP (echo_area_buffer[this_one]))
12401 {
12402 echo_area_buffer[this_one]
12403 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12404 ? echo_buffer[the_other]
12405 : echo_buffer[this_one]);
12406 clear_buffer_p = true;
12407 }
12408
12409 buffer = echo_area_buffer[this_one];
12410
12411
12412
12413 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12414 cancel_echoing ();
12415
12416 record_unwind_protect (unwind_with_echo_area_buffer,
12417 with_echo_area_buffer_unwind_data (w));
12418
12419
12420
12421
12422
12423
12424
12425
12426 set_buffer_internal_1 (XBUFFER (buffer));
12427 if (w)
12428 {
12429 wset_buffer (w, buffer);
12430 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12431 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12432 }
12433
12434 bset_undo_list (current_buffer, Qt);
12435 bset_read_only (current_buffer, Qnil);
12436 specbind (Qinhibit_read_only, Qt);
12437 specbind (Qinhibit_modification_hooks, Qt);
12438
12439 if (clear_buffer_p && Z > BEG)
12440 del_range (BEG, Z);
12441
12442 eassert (BEGV >= BEG);
12443 eassert (ZV <= Z && ZV >= BEGV);
12444
12445 rc = fn (a1, a2);
12446
12447 eassert (BEGV >= BEG);
12448 eassert (ZV <= Z && ZV >= BEGV);
12449
12450 unbind_to (count, Qnil);
12451 return rc;
12452 }
12453
12454
12455
12456
12457
12458 static Lisp_Object
12459 with_echo_area_buffer_unwind_data (struct window *w)
12460 {
12461 int i = 0;
12462 Lisp_Object vector, tmp;
12463
12464
12465
12466 vector = Vwith_echo_area_save_vector;
12467 Vwith_echo_area_save_vector = Qnil;
12468
12469 if (NILP (vector))
12470 vector = make_nil_vector (11);
12471
12472 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12473 ASET (vector, i, Vdeactivate_mark); ++i;
12474 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12475
12476 if (w)
12477 {
12478 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12479 ASET (vector, i, w->contents); ++i;
12480 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12481 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12482 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12483 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12484 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12485 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12486 }
12487 else
12488 {
12489 int end = i + 8;
12490 for (; i < end; ++i)
12491 ASET (vector, i, Qnil);
12492 }
12493
12494 eassert (i == ASIZE (vector));
12495 return vector;
12496 }
12497
12498
12499
12500
12501
12502 static void
12503 unwind_with_echo_area_buffer (Lisp_Object vector)
12504 {
12505 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12506 Vdeactivate_mark = AREF (vector, 1);
12507 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12508
12509 if (WINDOWP (AREF (vector, 3)))
12510 {
12511 struct window *w;
12512 Lisp_Object buffer;
12513
12514 w = XWINDOW (AREF (vector, 3));
12515 buffer = AREF (vector, 4);
12516
12517 wset_buffer (w, buffer);
12518 set_marker_restricted_both (w->pointm, buffer,
12519 XFIXNAT (AREF (vector, 5)),
12520 XFIXNAT (AREF (vector, 6)));
12521 set_marker_restricted_both (w->old_pointm, buffer,
12522 XFIXNAT (AREF (vector, 7)),
12523 XFIXNAT (AREF (vector, 8)));
12524 set_marker_restricted_both (w->start, buffer,
12525 XFIXNAT (AREF (vector, 9)),
12526 XFIXNAT (AREF (vector, 10)));
12527 }
12528
12529 Vwith_echo_area_save_vector = vector;
12530 }
12531
12532
12533
12534
12535
12536 void
12537 setup_echo_area_for_printing (bool multibyte_p)
12538 {
12539
12540 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12541 Fkill_emacs (Qnil, Qnil);
12542
12543 ensure_echo_area_buffers ();
12544
12545 if (!message_buf_print)
12546 {
12547
12548
12549 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12550 echo_area_buffer[0] = echo_buffer[1];
12551 else
12552 echo_area_buffer[0] = echo_buffer[0];
12553
12554
12555 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12556 bset_truncate_lines (current_buffer, Qnil);
12557
12558 if (Z > BEG)
12559 {
12560 specpdl_ref count = SPECPDL_INDEX ();
12561 specbind (Qinhibit_read_only, Qt);
12562
12563 del_range (BEG, Z);
12564 unbind_to (count, Qnil);
12565 }
12566 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12567
12568
12569
12570
12571
12572
12573
12574 if (unibyte_display_via_language_environment
12575 && !multibyte_p
12576 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12577 Fset_buffer_multibyte (Qnil);
12578 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12579 Fset_buffer_multibyte (Qt);
12580
12581
12582 if (minibuffer_auto_raise)
12583 {
12584 struct frame *sf = SELECTED_FRAME ();
12585 Lisp_Object mini_window;
12586 mini_window = FRAME_MINIBUF_WINDOW (sf);
12587 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12588 }
12589
12590 message_log_maybe_newline ();
12591 message_buf_print = true;
12592 }
12593 else
12594 {
12595 if (NILP (echo_area_buffer[0]))
12596 {
12597 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12598 echo_area_buffer[0] = echo_buffer[1];
12599 else
12600 echo_area_buffer[0] = echo_buffer[0];
12601 }
12602
12603 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12604 {
12605
12606 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12607 bset_truncate_lines (current_buffer, Qnil);
12608 }
12609 }
12610 }
12611
12612
12613
12614
12615
12616
12617
12618 static bool
12619 display_echo_area (struct window *w)
12620 {
12621 bool no_message_p, window_height_changed_p;
12622
12623
12624
12625
12626
12627
12628 specpdl_ref count = inhibit_garbage_collection ();
12629
12630
12631
12632
12633
12634 bool i = display_last_displayed_message_p;
12635
12636
12637
12638 no_message_p = NILP (echo_area_buffer[i]);
12639
12640 window_height_changed_p
12641 = with_echo_area_buffer (w, display_last_displayed_message_p,
12642 display_echo_area_1, w, Qnil);
12643
12644 if (no_message_p)
12645 echo_area_buffer[i] = Qnil;
12646
12647 unbind_to (count, Qnil);
12648 return window_height_changed_p;
12649 }
12650
12651
12652
12653
12654
12655
12656
12657
12658 static bool
12659 display_echo_area_1 (void *a1, Lisp_Object a2)
12660 {
12661 struct window *w = a1;
12662 Lisp_Object window;
12663 struct text_pos start;
12664
12665
12666
12667
12668 forget_escape_and_glyphless_faces ();
12669
12670
12671
12672
12673 bool window_height_changed_p = resize_mini_window (w, false);
12674
12675
12676 SET_TEXT_POS_FROM_MARKER (start, w->start);
12677
12678
12679 clear_glyph_matrix (w->desired_matrix);
12680 XSETWINDOW (window, w);
12681 void *itdata = bidi_shelve_cache ();
12682 try_window (window, start, 0);
12683 bidi_unshelve_cache (itdata, false);
12684
12685 return window_height_changed_p;
12686 }
12687
12688
12689
12690
12691
12692
12693 void
12694 resize_echo_area_exactly (void)
12695 {
12696 if (BUFFERP (echo_area_buffer[0])
12697 && WINDOWP (echo_area_window))
12698 {
12699 struct window *w = XWINDOW (echo_area_window);
12700 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12701 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12702 w, resize_exactly);
12703 if (resized_p)
12704 {
12705 windows_or_buffers_changed = 42;
12706 update_mode_lines = 30;
12707 redisplay_internal ();
12708 }
12709 }
12710 }
12711
12712
12713
12714
12715
12716
12717
12718
12719 static bool
12720 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12721 {
12722 return resize_mini_window (a1, !NILP (exactly));
12723 }
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737 bool
12738 resize_mini_window (struct window *w, bool exact_p)
12739 {
12740 struct frame *f = XFRAME (w->frame);
12741 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12742
12743 eassert (MINI_WINDOW_P (w));
12744
12745
12746
12747
12748
12749
12750
12751 if (!NILP (Vinhibit_redisplay))
12752 return false;
12753
12754
12755 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12756 set_marker_both (w->start, w->contents,
12757 BUF_BEGV (XBUFFER (w->contents)),
12758 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12759
12760
12761 if ((NILP (Vresize_mini_windows)
12762 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12763 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12764 return false;
12765
12766 if (FRAME_MINIBUF_ONLY_P (f))
12767 {
12768 if (!NILP (resize_mini_frames))
12769 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12770 }
12771 else
12772 {
12773 struct it it;
12774 int unit = FRAME_LINE_HEIGHT (f);
12775 int height, max_height;
12776 struct text_pos start;
12777 struct buffer *old_current_buffer = NULL;
12778 int windows_height = FRAME_INNER_HEIGHT (f);
12779
12780 if (current_buffer != XBUFFER (w->contents))
12781 {
12782 old_current_buffer = current_buffer;
12783 set_buffer_internal (XBUFFER (w->contents));
12784 }
12785
12786 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12787
12788
12789 if (FLOATP (Vmax_mini_window_height))
12790 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12791 else if (FIXNUMP (Vmax_mini_window_height))
12792 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12793 else
12794 max_height = windows_height / 4;
12795
12796
12797 max_height = clip_to_bounds (unit, max_height, windows_height);
12798
12799
12800 last_height = 0;
12801 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12802
12803
12804 if (it.max_ascent == 0 && it.max_descent == 0)
12805 {
12806 height = it.current_y;
12807
12808
12809
12810
12811
12812 if (!(it.line_wrap == TRUNCATE
12813 && it.current_x <= it.first_visible_x
12814 && ZV_BYTE > 1
12815 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12816 height += last_height;
12817 }
12818 else
12819 height = it.current_y + it.max_ascent + it.max_descent;
12820 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12821
12822
12823 if (height > max_height)
12824 {
12825 height = (max_height / unit) * unit;
12826 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12827 {
12828 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12829 move_it_vertically_backward (&it, height - unit);
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839 move_it_by_lines (&it, 0);
12840 start = it.current.pos;
12841
12842
12843 w->start_at_line_beg = false;
12844 SET_MARKER_FROM_TEXT_POS (w->start, start);
12845 }
12846 }
12847 else
12848 {
12849 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12850 SET_MARKER_FROM_TEXT_POS (w->start, start);
12851 }
12852
12853 if (EQ (Vresize_mini_windows, Qgrow_only))
12854 {
12855
12856
12857 if (height > old_height)
12858 grow_mini_window (w, height - old_height);
12859 else if (height < old_height && (exact_p || BEGV == ZV))
12860 shrink_mini_window (w);
12861 }
12862 else if (height != old_height)
12863
12864 grow_mini_window (w, height - old_height);
12865
12866 if (old_current_buffer)
12867 set_buffer_internal (old_current_buffer);
12868 }
12869
12870 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12871 }
12872
12873
12874
12875
12876
12877 Lisp_Object
12878 current_message (void)
12879 {
12880 Lisp_Object msg;
12881
12882 if (!BUFFERP (echo_area_buffer[0]))
12883 msg = Qnil;
12884 else
12885 {
12886 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12887 if (NILP (msg))
12888 echo_area_buffer[0] = Qnil;
12889 }
12890
12891 return msg;
12892 }
12893
12894
12895 static bool
12896 current_message_1 (void *a1, Lisp_Object a2)
12897 {
12898 Lisp_Object *msg = a1;
12899
12900 if (Z > BEG)
12901 *msg = make_buffer_string (BEG, Z, true);
12902 else
12903 *msg = Qnil;
12904 return false;
12905 }
12906
12907
12908
12909
12910
12911
12912
12913 bool
12914 push_message (void)
12915 {
12916 Lisp_Object msg = current_message ();
12917 Vmessage_stack = Fcons (msg, Vmessage_stack);
12918 return STRINGP (msg);
12919 }
12920
12921
12922
12923
12924 void
12925 restore_message (void)
12926 {
12927 eassert (CONSP (Vmessage_stack));
12928 message3_nolog (XCAR (Vmessage_stack));
12929 }
12930
12931
12932
12933
12934 void
12935 pop_message_unwind (void)
12936 {
12937
12938 eassert (CONSP (Vmessage_stack));
12939 Vmessage_stack = XCDR (Vmessage_stack);
12940 }
12941
12942
12943
12944
12945
12946
12947 void
12948 check_message_stack (void)
12949 {
12950 if (!NILP (Vmessage_stack))
12951 emacs_abort ();
12952 }
12953
12954 void
12955 clear_message_stack (void)
12956 {
12957 Vmessage_stack = Qnil;
12958 }
12959
12960
12961
12962
12963 void
12964 truncate_echo_area (ptrdiff_t nchars)
12965 {
12966 if (nchars == 0)
12967 echo_area_buffer[0] = Qnil;
12968 else if (!noninteractive
12969 && INTERACTIVE
12970 && !NILP (echo_area_buffer[0]))
12971 {
12972 struct frame *sf = SELECTED_FRAME ();
12973
12974
12975
12976 if (sf->glyphs_initialized_p)
12977 with_echo_area_buffer (0, 0, truncate_message_1,
12978 (void *) (intptr_t) nchars, Qnil);
12979 }
12980 }
12981
12982
12983
12984
12985
12986 static bool
12987 truncate_message_1 (void *a1, Lisp_Object a2)
12988 {
12989 intptr_t nchars = (intptr_t) a1;
12990 if (BEG + nchars < Z)
12991 del_range (BEG + nchars, Z);
12992 if (Z == BEG)
12993 echo_area_buffer[0] = Qnil;
12994 return false;
12995 }
12996
12997 extern intptr_t garbage_collection_inhibited;
12998
12999
13000
13001 static void
13002 set_message (Lisp_Object string)
13003 {
13004 Lisp_Object message = Qnil;
13005
13006 eassert (STRINGP (string));
13007
13008 if (FUNCTIONP (Vset_message_function)
13009
13010
13011
13012 && !garbage_collection_inhibited)
13013 {
13014 specpdl_ref count = SPECPDL_INDEX ();
13015 specbind (Qinhibit_quit, Qt);
13016 message = safe_call1 (Vset_message_function, string);
13017 unbind_to (count, Qnil);
13018
13019 if (STRINGP (message))
13020 {
13021 string = message;
13022 message = Qnil;
13023 }
13024 }
13025
13026 if (NILP (message))
13027 {
13028 message_enable_multibyte = STRING_MULTIBYTE (string);
13029
13030 with_echo_area_buffer (0, -1, set_message_1, 0, string);
13031 message_buf_print = false;
13032 help_echo_showing_p = false;
13033 }
13034
13035 if (STRINGP (Vdebug_on_message)
13036 && STRINGP (string)
13037 && fast_string_match (Vdebug_on_message, string) >= 0)
13038 call_debugger (list2 (Qerror, string));
13039 }
13040
13041
13042
13043
13044
13045
13046 static bool
13047 set_message_1 (void *a1, Lisp_Object string)
13048 {
13049 eassert (STRINGP (string));
13050
13051
13052
13053
13054
13055
13056 if (!message_enable_multibyte
13057 && unibyte_display_via_language_environment
13058 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13059 Fset_buffer_multibyte (Qnil);
13060 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13061 Fset_buffer_multibyte (Qt);
13062
13063 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13064 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13065 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13066
13067
13068 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13069
13070
13071
13072
13073 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13074
13075 return false;
13076 }
13077
13078
13079
13080
13081
13082 void
13083 clear_message (bool current_p, bool last_displayed_p)
13084 {
13085 Lisp_Object preserve = Qnil;
13086
13087 if (current_p)
13088 {
13089 if (FUNCTIONP (Vclear_message_function)
13090
13091 && !garbage_collection_inhibited)
13092 {
13093 specpdl_ref count = SPECPDL_INDEX ();
13094 specbind (Qinhibit_quit, Qt);
13095 preserve = safe_call (1, Vclear_message_function);
13096 unbind_to (count, Qnil);
13097 }
13098
13099 if (!EQ (preserve, Qdont_clear_message))
13100 {
13101 echo_area_buffer[0] = Qnil;
13102 message_cleared_p = true;
13103 }
13104 }
13105
13106 if (last_displayed_p)
13107 echo_area_buffer[1] = Qnil;
13108
13109 message_buf_print = false;
13110 }
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121 static void
13122 clear_garbaged_frames (void)
13123 {
13124 if (frame_garbaged)
13125 {
13126 Lisp_Object tail, frame;
13127 struct frame *sf = SELECTED_FRAME ();
13128
13129 FOR_EACH_FRAME (tail, frame)
13130 {
13131 struct frame *f = XFRAME (frame);
13132
13133 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13134 {
13135 if (f->resized_p
13136
13137
13138
13139
13140
13141 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13142 redraw_frame (f);
13143 else
13144 clear_current_matrices (f);
13145
13146 #ifdef HAVE_WINDOW_SYSTEM
13147 if (FRAME_WINDOW_P (f)
13148 && FRAME_RIF (f)->clear_under_internal_border)
13149 FRAME_RIF (f)->clear_under_internal_border (f);
13150 #endif
13151 fset_redisplay (f);
13152 f->garbaged = false;
13153 f->resized_p = false;
13154 }
13155 }
13156
13157 frame_garbaged = false;
13158 }
13159 }
13160
13161
13162
13163
13164
13165 static void
13166 echo_area_display (bool update_frame_p)
13167 {
13168 Lisp_Object mini_window;
13169 struct window *w;
13170 struct frame *f;
13171 bool window_height_changed_p = false;
13172 struct frame *sf = SELECTED_FRAME ();
13173
13174 mini_window = FRAME_MINIBUF_WINDOW (sf);
13175 if (NILP (mini_window))
13176 return;
13177
13178 w = XWINDOW (mini_window);
13179 f = XFRAME (WINDOW_FRAME (w));
13180
13181
13182 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13183 return;
13184
13185 #ifdef HAVE_WINDOW_SYSTEM
13186
13187
13188
13189 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13190 return;
13191 #endif
13192
13193
13194 clear_garbaged_frames ();
13195
13196 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13197 {
13198 echo_area_window = mini_window;
13199 window_height_changed_p = display_echo_area (w);
13200 w->must_be_updated_p = true;
13201
13202
13203
13204
13205
13206 if (update_frame_p && !redisplaying_p)
13207 {
13208 int n = 0;
13209
13210
13211
13212
13213
13214
13215 if (!display_completed)
13216 {
13217 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13218
13219 #ifdef HAVE_WINDOW_SYSTEM
13220 if (FRAME_WINDOW_P (f)
13221 && FRAME_RIF (f)->clear_under_internal_border)
13222 FRAME_RIF (f)->clear_under_internal_border (f);
13223 #endif
13224 }
13225
13226 if (window_height_changed_p
13227
13228
13229 && !NILP (Vrun_hooks))
13230 {
13231
13232
13233
13234 specpdl_ref count = SPECPDL_INDEX ();
13235 specbind (Qredisplay_dont_pause, Qt);
13236 fset_redisplay (f);
13237 redisplay_internal ();
13238 unbind_to (count, Qnil);
13239 }
13240 else if (FRAME_WINDOW_P (f) && n == 0)
13241 {
13242
13243
13244
13245 update_single_window (w);
13246 flush_frame (f);
13247 }
13248 else
13249 update_frame (f, true, true);
13250
13251
13252
13253
13254 if (cursor_in_echo_area)
13255 wset_redisplay (XWINDOW (mini_window));
13256 }
13257 }
13258 else if (!EQ (mini_window, selected_window))
13259 wset_redisplay (XWINDOW (mini_window));
13260
13261
13262 echo_area_buffer[1] = echo_area_buffer[0];
13263
13264 echo_message_buffer = Qnil;
13265
13266
13267
13268
13269 if (EQ (mini_window, selected_window))
13270 CHARPOS (this_line_start_pos) = 0;
13271
13272 if (window_height_changed_p)
13273 {
13274 fset_redisplay (f);
13275
13276
13277
13278
13279
13280 clear_garbaged_frames ();
13281 }
13282 }
13283
13284
13285
13286 static bool
13287 window_buffer_changed (struct window *w)
13288 {
13289 struct buffer *b = XBUFFER (w->contents);
13290
13291 eassert (BUFFER_LIVE_P (b));
13292
13293 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13294 }
13295
13296
13297
13298 static bool
13299 mode_line_update_needed (struct window *w)
13300 {
13301 return (w->column_number_displayed != -1
13302 && !(PT == w->last_point && !window_outdated (w))
13303 && (w->column_number_displayed != current_column ()));
13304 }
13305
13306
13307
13308
13309 static bool
13310 window_frozen_p (struct window *w)
13311 {
13312 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13313 {
13314 Lisp_Object window;
13315
13316 XSETWINDOW (window, w);
13317 if (MINI_WINDOW_P (w))
13318 return false;
13319 else if (EQ (window, selected_window))
13320 return false;
13321 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13322 && EQ (window, Vminibuf_scroll_window))
13323
13324 return false;
13325 else
13326 return true;
13327 }
13328 return false;
13329 }
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339 static char *mode_line_noprop_buf;
13340
13341
13342
13343 static char *mode_line_noprop_buf_end;
13344 static char *mode_line_noprop_ptr;
13345
13346 #define MODE_LINE_NOPROP_LEN(start) \
13347 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13348
13349 static enum {
13350 MODE_LINE_DISPLAY = 0,
13351 MODE_LINE_TITLE,
13352 MODE_LINE_NOPROP,
13353 MODE_LINE_STRING
13354 } mode_line_target;
13355
13356
13357
13358 static Lisp_Object mode_line_proptrans_alist;
13359
13360
13361 static Lisp_Object mode_line_string_list;
13362
13363
13364 static Lisp_Object mode_line_string_face;
13365 static Lisp_Object mode_line_string_face_prop;
13366
13367
13368
13369
13370 static Lisp_Object Vmode_line_unwind_vector;
13371
13372 static Lisp_Object
13373 format_mode_line_unwind_data (struct frame *target_frame,
13374 struct buffer *obuf,
13375 Lisp_Object owin,
13376 bool save_proptrans)
13377 {
13378 Lisp_Object vector, tmp;
13379
13380
13381
13382 vector = Vmode_line_unwind_vector;
13383 Vmode_line_unwind_vector = Qnil;
13384
13385 if (NILP (vector))
13386 vector = make_nil_vector (12);
13387
13388 ASET (vector, 0, make_fixnum (mode_line_target));
13389 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13390 ASET (vector, 2, mode_line_string_list);
13391 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13392 ASET (vector, 4, mode_line_string_face);
13393 ASET (vector, 5, mode_line_string_face_prop);
13394
13395 if (obuf)
13396 XSETBUFFER (tmp, obuf);
13397 else
13398 tmp = Qnil;
13399 ASET (vector, 6, tmp);
13400 ASET (vector, 7, owin);
13401 if (target_frame)
13402 {
13403 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13404 struct buffer *b = XBUFFER (buffer);
13405 struct buffer *cb = current_buffer;
13406
13407
13408
13409
13410 ASET (vector, 8, target_frame->selected_window);
13411 if (FRAME_TERMCAP_P (target_frame))
13412 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13413
13414
13415
13416
13417 ASET (vector, 10, buffer);
13418 current_buffer = b;
13419 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13420 current_buffer = cb;
13421 }
13422
13423 return vector;
13424 }
13425
13426 static void
13427 unwind_format_mode_line (Lisp_Object vector)
13428 {
13429 Lisp_Object old_window = AREF (vector, 7);
13430 Lisp_Object target_frame_window = AREF (vector, 8);
13431 Lisp_Object old_top_frame = AREF (vector, 9);
13432
13433 mode_line_target = XFIXNUM (AREF (vector, 0));
13434 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13435 mode_line_string_list = AREF (vector, 2);
13436 if (! EQ (AREF (vector, 3), Qt))
13437 mode_line_proptrans_alist = AREF (vector, 3);
13438 mode_line_string_face = AREF (vector, 4);
13439 mode_line_string_face_prop = AREF (vector, 5);
13440
13441
13442 if (WINDOW_LIVE_P (old_window))
13443 {
13444
13445
13446
13447 if (WINDOW_LIVE_P (target_frame_window))
13448 {
13449 Lisp_Object frame
13450 = WINDOW_FRAME (XWINDOW (target_frame_window));
13451
13452 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13453 Fselect_window (target_frame_window, Qt);
13454
13455 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13456
13457
13458 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13459 Fselect_frame (old_top_frame, Qt);
13460 }
13461
13462 Fselect_window (old_window, Qt);
13463
13464
13465
13466
13467 if (WINDOW_LIVE_P (target_frame_window))
13468 {
13469 Lisp_Object buffer = AREF (vector, 10);
13470
13471 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13472 {
13473 struct buffer *cb = current_buffer;
13474
13475 current_buffer = XBUFFER (buffer);
13476 set_point_from_marker (AREF (vector, 11));
13477 ASET (vector, 11, Qnil);
13478 current_buffer = cb;
13479 }
13480 }
13481 }
13482
13483 if (!NILP (AREF (vector, 6)))
13484 {
13485 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13486 ASET (vector, 6, Qnil);
13487 }
13488
13489 Vmode_line_unwind_vector = vector;
13490 }
13491
13492
13493
13494
13495
13496 static void
13497 store_mode_line_noprop_char (char c)
13498 {
13499
13500
13501 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13502 {
13503 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13504 ptrdiff_t size = len;
13505 mode_line_noprop_buf =
13506 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13507 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13508 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13509 }
13510
13511 *mode_line_noprop_ptr++ = c;
13512 }
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523 static int
13524 store_mode_line_noprop (const char *string, int field_width, int precision)
13525 {
13526 const unsigned char *str = (const unsigned char *) string;
13527 int n = 0;
13528 ptrdiff_t dummy, nbytes;
13529
13530
13531 nbytes = strlen (string);
13532 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13533 while (nbytes--)
13534 store_mode_line_noprop_char (*str++);
13535
13536
13537 while (field_width > 0
13538 && n < field_width)
13539 {
13540 store_mode_line_noprop_char (' ');
13541 ++n;
13542 }
13543
13544 return n;
13545 }
13546
13547
13548
13549
13550
13551 #ifdef HAVE_WINDOW_SYSTEM
13552
13553
13554
13555
13556
13557 void
13558 gui_consider_frame_title (Lisp_Object frame)
13559 {
13560 struct frame *f = XFRAME (frame);
13561 Lisp_Object format_data;
13562
13563 if ((FRAME_WINDOW_P (f)
13564 || FRAME_MINIBUF_ONLY_P (f)
13565 || f->explicit_name)
13566 && !FRAME_TOOLTIP_P (f))
13567 {
13568
13569 Lisp_Object tail, other_frame, fmt;
13570 ptrdiff_t title_start;
13571 char *title;
13572 ptrdiff_t len;
13573 struct it it;
13574 specpdl_ref count = SPECPDL_INDEX ();
13575
13576 FOR_EACH_FRAME (tail, other_frame)
13577 {
13578 struct frame *tf = XFRAME (other_frame);
13579
13580 if (tf != f
13581 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13582 && !FRAME_MINIBUF_ONLY_P (tf)
13583 && !FRAME_PARENT_FRAME (tf)
13584 && !FRAME_TOOLTIP_P (tf)
13585 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13586 break;
13587 }
13588
13589
13590 multiple_frames = CONSP (tail);
13591
13592
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603 specbind (Qinhibit_redisplay, Qt);
13604
13605
13606
13607
13608
13609
13610
13611
13612 format_data = format_mode_line_unwind_data (f, current_buffer,
13613 selected_window,
13614 false);
13615 record_unwind_protect (unwind_format_mode_line, format_data);
13616
13617 Fselect_window (f->selected_window, Qt);
13618 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13619 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13620 ? Vicon_title_format : Vframe_title_format);
13621
13622 mode_line_target = MODE_LINE_TITLE;
13623 title_start = MODE_LINE_NOPROP_LEN (0);
13624 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13625 NULL, DEFAULT_FACE_ID);
13626 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13627 len = MODE_LINE_NOPROP_LEN (title_start);
13628 title = mode_line_noprop_buf + title_start;
13629
13630
13631 ptrdiff_t nchars = 0;
13632 len = str_as_multibyte ((unsigned char *) title,
13633 mode_line_noprop_buf_end - title,
13634 len, &nchars);
13635 unbind_to (count, Qnil);
13636
13637
13638
13639
13640
13641
13642 if ((! STRINGP (f->name)
13643 || SBYTES (f->name) != len
13644 || memcmp (title, SDATA (f->name), len) != 0)
13645 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13646 {
13647 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13648 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13649 }
13650 }
13651 }
13652
13653 #endif
13654
13655
13656
13657
13658
13659
13660
13661 #define REDISPLAY_SOME_P() \
13662 ((windows_or_buffers_changed == 0 \
13663 || windows_or_buffers_changed == REDISPLAY_SOME) \
13664 && (update_mode_lines == 0 \
13665 || update_mode_lines == REDISPLAY_SOME))
13666
13667 static bool
13668 needs_no_redisplay (struct window *w)
13669 {
13670 struct buffer *buffer = XBUFFER (w->contents);
13671 struct frame *f = XFRAME (w->frame);
13672 return (REDISPLAY_SOME_P ()
13673 && !w->redisplay
13674 && !w->update_mode_line
13675 && !f->face_change
13676 && !f->redisplay
13677 && !buffer->text->redisplay
13678 && window_point (w) == w->last_point);
13679 }
13680
13681
13682
13683
13684 static void
13685 prepare_menu_bars (void)
13686 {
13687 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13688 bool some_windows = REDISPLAY_SOME_P ();
13689
13690 if (FUNCTIONP (Vpre_redisplay_function))
13691 {
13692 Lisp_Object windows = all_windows ? Qt : Qnil;
13693 if (all_windows && some_windows)
13694 {
13695 Lisp_Object ws = window_list ();
13696 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13697 {
13698 Lisp_Object this = XCAR (ws);
13699 struct window *w = XWINDOW (this);
13700
13701
13702 if (!needs_no_redisplay (w))
13703 windows = Fcons (this, windows);
13704 }
13705 }
13706 safe__call1 (true, Vpre_redisplay_function, windows);
13707 }
13708
13709
13710
13711
13712 #ifdef HAVE_WINDOW_SYSTEM
13713 if (all_windows)
13714 {
13715 Lisp_Object tail, frame;
13716
13717 FOR_EACH_FRAME (tail, frame)
13718 {
13719 struct frame *f = XFRAME (frame);
13720 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13721 if (some_windows
13722 && !f->redisplay
13723 && !w->redisplay
13724 && !XBUFFER (w->contents)->text->redisplay)
13725 continue;
13726
13727 if (!FRAME_TOOLTIP_P (f)
13728 && (FRAME_ICONIFIED_P (f)
13729 || FRAME_VISIBLE_P (f) == 1
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13740 gui_consider_frame_title (frame);
13741 }
13742 }
13743 #endif
13744
13745
13746
13747
13748 if (all_windows)
13749 {
13750 Lisp_Object tail, frame;
13751 specpdl_ref count = SPECPDL_INDEX ();
13752
13753
13754 bool menu_bar_hooks_run = false;
13755
13756 record_unwind_save_match_data ();
13757
13758 FOR_EACH_FRAME (tail, frame)
13759 {
13760 struct frame *f = XFRAME (frame);
13761 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13762
13763
13764 if (FRAME_TOOLTIP_P (f))
13765 continue;
13766
13767 if (some_windows
13768 && !f->redisplay
13769 && !w->redisplay
13770 && !XBUFFER (w->contents)->text->redisplay)
13771 continue;
13772
13773 if (!FRAME_PARENT_FRAME (f))
13774 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13775
13776 update_tab_bar (f, false);
13777 #ifdef HAVE_WINDOW_SYSTEM
13778 update_tool_bar (f, false);
13779 #endif
13780 }
13781
13782 unbind_to (count, Qnil);
13783 }
13784 else
13785 {
13786 struct frame *sf = SELECTED_FRAME ();
13787
13788 if (!FRAME_PARENT_FRAME (sf))
13789 update_menu_bar (sf, true, false);
13790
13791 update_tab_bar (sf, true);
13792 #ifdef HAVE_WINDOW_SYSTEM
13793 update_tool_bar (sf, true);
13794 #endif
13795 }
13796 }
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810 static bool
13811 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13812 {
13813 Lisp_Object window;
13814 struct window *w;
13815
13816
13817
13818
13819 if (inhibit_menubar_update)
13820 return hooks_run;
13821
13822 window = FRAME_SELECTED_WINDOW (f);
13823 w = XWINDOW (window);
13824
13825 if (FRAME_WINDOW_P (f)
13826 ?
13827 #ifdef HAVE_EXT_MENU_BAR
13828 FRAME_EXTERNAL_MENU_BAR (f)
13829 #else
13830 FRAME_MENU_BAR_LINES (f) > 0
13831 #endif
13832 : FRAME_MENU_BAR_LINES (f) > 0)
13833 {
13834
13835
13836
13837
13838
13839
13840
13841 if (windows_or_buffers_changed
13842
13843
13844 || update_mode_lines
13845 || window_buffer_changed (w))
13846 {
13847 struct buffer *prev = current_buffer;
13848 specpdl_ref count = SPECPDL_INDEX ();
13849
13850 specbind (Qinhibit_menubar_update, Qt);
13851
13852 set_buffer_internal_1 (XBUFFER (w->contents));
13853 if (save_match_data)
13854 record_unwind_save_match_data ();
13855 if (NILP (Voverriding_local_map_menu_flag))
13856 {
13857 specbind (Qoverriding_terminal_local_map, Qnil);
13858 specbind (Qoverriding_local_map, Qnil);
13859 }
13860
13861 if (!hooks_run)
13862 {
13863
13864 safe_run_hooks (Qactivate_menubar_hook);
13865
13866
13867
13868 safe_run_hooks (Qmenu_bar_update_hook);
13869
13870 hooks_run = true;
13871 }
13872
13873 XSETFRAME (Vmenu_updating_frame, f);
13874 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13875
13876
13877 #ifdef HAVE_EXT_MENU_BAR
13878 if (FRAME_WINDOW_P (f))
13879 {
13880 #if defined (HAVE_NS)
13881
13882
13883 if (f == SELECTED_FRAME ())
13884 #endif
13885 set_frame_menubar (f, false);
13886 }
13887 else
13888
13889
13890 w->update_mode_line = true;
13891 #else
13892
13893
13894 w->update_mode_line = true;
13895 #endif
13896
13897 unbind_to (count, Qnil);
13898 set_buffer_internal_1 (prev);
13899 }
13900 }
13901
13902 return hooks_run;
13903 }
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916 static void
13917 restore_selected_window (Lisp_Object window)
13918 {
13919 if (WINDOW_LIVE_P (window))
13920
13921
13922 {
13923 selected_window = window;
13924 selected_frame = XWINDOW (window)->frame;
13925 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13926 }
13927 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13928
13929
13930 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13931 else
13932
13933
13934
13935 {
13936 Lisp_Object tail;
13937 Lisp_Object frame UNINIT;
13938
13939 FOR_EACH_FRAME (tail, frame)
13940 {
13941 struct frame *f = XFRAME (frame);
13942
13943 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13944 {
13945 selected_frame = frame;
13946 selected_window = FRAME_SELECTED_WINDOW (f);
13947
13948 return;
13949 }
13950 }
13951
13952
13953 emacs_abort ();
13954 }
13955 }
13956
13957
13958 static void
13959 restore_frame_selected_window (Lisp_Object window)
13960 {
13961 if (WINDOW_LIVE_P (window))
13962
13963
13964
13965 {
13966 Lisp_Object frame = XWINDOW (window)->frame;
13967
13968 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13969 if (EQ (frame, selected_frame))
13970 selected_window = window;
13971 }
13972 }
13973
13974
13975
13976
13977
13978
13979 static void
13980 update_tab_bar (struct frame *f, bool save_match_data)
13981 {
13982 bool do_update = false;
13983
13984 #ifdef HAVE_WINDOW_SYSTEM
13985 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13986 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13987 do_update = true;
13988 }
13989 else
13990 #endif
13991 if (FRAME_TAB_BAR_LINES (f) > 0)
13992 do_update = true;
13993
13994 if (do_update)
13995 {
13996 Lisp_Object window;
13997 struct window *w;
13998
13999 window = FRAME_SELECTED_WINDOW (f);
14000 w = XWINDOW (window);
14001
14002
14003
14004
14005
14006
14007
14008
14009 if (windows_or_buffers_changed
14010 || w->update_mode_line
14011 || update_mode_lines
14012 || window_buffer_changed (w))
14013 {
14014 struct buffer *prev = current_buffer;
14015 specpdl_ref count = SPECPDL_INDEX ();
14016 Lisp_Object new_tab_bar;
14017 int new_n_tab_bar;
14018
14019
14020
14021
14022 set_buffer_internal_1 (XBUFFER (w->contents));
14023
14024
14025 if (save_match_data)
14026 record_unwind_save_match_data ();
14027
14028
14029 if (NILP (Voverriding_local_map_menu_flag))
14030 {
14031 specbind (Qoverriding_terminal_local_map, Qnil);
14032 specbind (Qoverriding_local_map, Qnil);
14033 }
14034
14035
14036
14037
14038
14039 eassert (EQ (selected_window,
14040
14041
14042 XFRAME (selected_frame)->selected_window));
14043 #ifdef HAVE_WINDOW_SYSTEM
14044 Lisp_Object frame;
14045 record_unwind_protect (restore_selected_window, selected_window);
14046 XSETFRAME (frame, f);
14047 selected_frame = frame;
14048 selected_window = FRAME_SELECTED_WINDOW (f);
14049 #endif
14050
14051
14052 new_tab_bar
14053 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14054 &new_n_tab_bar);
14055
14056
14057 if (new_n_tab_bar != f->n_tab_bar_items
14058 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14059 {
14060
14061
14062
14063 block_input ();
14064 fset_tab_bar_items (f, new_tab_bar);
14065 f->n_tab_bar_items = new_n_tab_bar;
14066 w->update_mode_line = true;
14067 unblock_input ();
14068 }
14069
14070 unbind_to (count, Qnil);
14071 set_buffer_internal_1 (prev);
14072 }
14073 }
14074 }
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086 static void
14087 display_tab_bar (struct window *w)
14088 {
14089 struct frame *f = XFRAME (WINDOW_FRAME (w));
14090 struct it it;
14091 Lisp_Object items;
14092 int i;
14093
14094
14095 #ifdef HAVE_NTGUI
14096 if (FRAME_W32_P (f))
14097 return;
14098 #endif
14099 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14100 if (FRAME_X_P (f))
14101 return;
14102 #endif
14103
14104 #ifdef HAVE_NS
14105 if (FRAME_NS_P (f))
14106 return;
14107 #endif
14108
14109 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14110 eassert (!FRAME_WINDOW_P (f));
14111 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14112 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14113 TAB_BAR_FACE_ID);
14114 it.first_visible_x = 0;
14115 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14116 #elif defined (HAVE_X_WINDOWS)
14117 if (FRAME_WINDOW_P (f))
14118 {
14119
14120
14121 struct window *tab_w;
14122 tab_w = XWINDOW (f->tab_bar_window);
14123 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14124 TAB_BAR_FACE_ID);
14125 it.first_visible_x = 0;
14126 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14127 }
14128 else
14129 #endif
14130 {
14131
14132
14133 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14134 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14135 TAB_BAR_FACE_ID);
14136 it.first_visible_x = 0;
14137 it.last_visible_x = FRAME_COLS (f);
14138 }
14139
14140
14141
14142
14143 it.paragraph_embedding = L2R;
14144
14145
14146 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14147 {
14148 struct glyph_row *row = it.glyph_row + i;
14149 clear_glyph_row (row);
14150 row->enabled_p = true;
14151 row->full_width_p = true;
14152 row->reversed_p = false;
14153 }
14154
14155
14156 items = it.f->tab_bar_items;
14157 int j;
14158 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14159 {
14160 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14161
14162
14163 if (NILP (string))
14164 break;
14165
14166 if (it.current_x < it.last_visible_x)
14167 display_string (NULL, string, Qnil, 0, 0, &it,
14168 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14169 }
14170
14171
14172 if (it.current_x < it.last_visible_x)
14173 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14174
14175
14176 compute_line_metrics (&it);
14177 }
14178
14179 #ifdef HAVE_WINDOW_SYSTEM
14180
14181
14182
14183
14184
14185 static void
14186 build_desired_tab_bar_string (struct frame *f)
14187 {
14188 int i;
14189 Lisp_Object caption;
14190
14191 caption = Qnil;
14192
14193
14194 fset_desired_tab_bar_string (f, build_string (""));
14195
14196
14197
14198
14199 for (i = 0; i < f->n_tab_bar_items; ++i)
14200 {
14201 #define PROP(IDX) \
14202 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14203
14204 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14205
14206
14207
14208
14209
14210 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14211
14212 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14213 props, caption);
14214
14215 f->desired_tab_bar_string =
14216 concat2 (f->desired_tab_bar_string, caption);
14217
14218 #undef PROP
14219 }
14220 }
14221
14222
14223
14224
14225
14226
14227
14228
14229
14230
14231
14232
14233
14234
14235 static void
14236 display_tab_bar_line (struct it *it, int height)
14237 {
14238 struct glyph_row *row = it->glyph_row;
14239 int max_x = it->last_visible_x;
14240 struct glyph *last;
14241
14242
14243 clear_glyph_row (row);
14244 row->enabled_p = true;
14245 row->y = it->current_y;
14246
14247
14248
14249 it->start_of_box_run_p = true;
14250
14251 bool enough = false;
14252 while (it->current_x < max_x)
14253 {
14254 int x, n_glyphs_before, i, nglyphs;
14255 struct it it_before;
14256
14257
14258 if (!get_next_display_element (it))
14259 {
14260
14261 if (height < 0 && !it->hpos)
14262 return;
14263 break;
14264 }
14265
14266
14267 n_glyphs_before = row->used[TEXT_AREA];
14268 it_before = *it;
14269
14270 PRODUCE_GLYPHS (it);
14271
14272 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14273 i = 0;
14274 x = it_before.current_x;
14275 while (i < nglyphs)
14276 {
14277 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14278
14279 if (x + glyph->pixel_width > max_x)
14280 {
14281
14282 row->used[TEXT_AREA] = n_glyphs_before;
14283 *it = it_before;
14284
14285
14286
14287 if (n_glyphs_before == 0
14288 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14289 break;
14290 goto out;
14291 }
14292
14293 ++it->hpos;
14294 x += glyph->pixel_width;
14295 ++i;
14296 }
14297
14298 enough = ITERATOR_AT_END_OF_LINE_P (it);
14299 set_iterator_to_next (it, true);
14300
14301
14302 if (enough)
14303 break;
14304 }
14305
14306 out:;
14307
14308 row->displays_text_p = row->used[TEXT_AREA] != 0;
14309
14310
14311
14312
14313
14314
14315
14316 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14317 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14318 it->face_id = DEFAULT_FACE_ID;
14319
14320 extend_face_to_end_of_line (it);
14321 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14322 last->right_box_line_p = true;
14323 if (last == row->glyphs[TEXT_AREA])
14324 last->left_box_line_p = true;
14325
14326
14327 if ((height -= it->max_ascent + it->max_descent) > 0)
14328 {
14329
14330 height %= FRAME_LINE_HEIGHT (it->f);
14331 it->max_ascent += height / 2;
14332 it->max_descent += (height + 1) / 2;
14333 }
14334
14335 compute_line_metrics (it);
14336
14337
14338 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14339 {
14340 row->height = row->phys_height = it->last_visible_y - row->y;
14341 row->visible_height = row->height;
14342 row->ascent = row->phys_ascent = 0;
14343 row->extra_line_spacing = 0;
14344 }
14345
14346 row->full_width_p = true;
14347 row->continued_p = false;
14348 row->truncated_on_left_p = false;
14349 row->truncated_on_right_p = false;
14350
14351 it->current_x = it->hpos = 0;
14352 it->current_y += row->height;
14353 ++it->vpos;
14354 ++it->glyph_row;
14355 }
14356
14357
14358
14359
14360
14361 static int
14362 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14363 {
14364 struct window *w = XWINDOW (f->tab_bar_window);
14365 struct it it;
14366
14367
14368
14369 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14370
14371
14372
14373 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14374 temp_row->reversed_p = false;
14375 it.first_visible_x = 0;
14376 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14377 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14378 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14379 it.paragraph_embedding = L2R;
14380
14381 clear_glyph_row (temp_row);
14382 while (!ITERATOR_AT_END_P (&it))
14383 {
14384 it.glyph_row = temp_row;
14385 display_tab_bar_line (&it, -1);
14386 }
14387 clear_glyph_row (temp_row);
14388
14389
14390 if (n_rows)
14391 *n_rows = it.vpos > 0 ? it.vpos : -1;
14392
14393 if (pixelwise)
14394 return it.current_y;
14395 else
14396 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14397 }
14398
14399 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14400 0, 2, 0,
14401 doc:
14402
14403 )
14404 (Lisp_Object frame, Lisp_Object pixelwise)
14405 {
14406 int height = 0;
14407
14408 struct frame *f = decode_any_frame (frame);
14409
14410 if (WINDOWP (f->tab_bar_window)
14411 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14412 {
14413 update_tab_bar (f, true);
14414 if (f->n_tab_bar_items)
14415 {
14416 build_desired_tab_bar_string (f);
14417 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14418 }
14419 }
14420
14421 return make_fixnum (height);
14422 }
14423
14424
14425
14426
14427 static bool
14428 redisplay_tab_bar (struct frame *f)
14429 {
14430 struct window *w;
14431 struct it it;
14432 struct glyph_row *row;
14433
14434 f->tab_bar_redisplayed = true;
14435
14436
14437
14438
14439
14440 if (!WINDOWP (f->tab_bar_window)
14441 || (w = XWINDOW (f->tab_bar_window),
14442 WINDOW_TOTAL_LINES (w) == 0))
14443 {
14444
14445
14446
14447
14448
14449 f->tab_bar_resized = true;
14450
14451 return false;
14452 }
14453
14454
14455 build_desired_tab_bar_string (f);
14456
14457 int new_nrows;
14458 int new_height = tab_bar_height (f, &new_nrows, true);
14459
14460 if (f->n_tab_bar_rows == 0)
14461 {
14462 f->n_tab_bar_rows = new_nrows;
14463 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14464 frame_default_tab_bar_height = new_height;
14465 }
14466
14467
14468
14469 if (new_nrows > f->n_tab_bar_rows
14470 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14471 && !f->minimize_tab_bar_window_p
14472 && new_height > WINDOW_PIXEL_HEIGHT (w))
14473 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14474 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14475 {
14476 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14477 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14478 if (new_nrows != f->n_tab_bar_rows)
14479 f->n_tab_bar_rows = new_nrows;
14480 clear_glyph_matrix (w->desired_matrix);
14481 f->fonts_changed = true;
14482 return true;
14483 }
14484
14485
14486 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14487 it.first_visible_x = 0;
14488 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14489 row = it.glyph_row;
14490 row->reversed_p = false;
14491 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14492 STRING_MULTIBYTE (f->desired_tab_bar_string));
14493
14494
14495
14496
14497
14498
14499
14500 it.paragraph_embedding = L2R;
14501
14502
14503
14504 if (f->n_tab_bar_rows > 0)
14505 {
14506 int border, rows, height, extra;
14507
14508 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14509 border = XFIXNUM (Vtab_bar_border);
14510 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14511 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14512 else if (EQ (Vtab_bar_border, Qborder_width))
14513 border = f->border_width;
14514 else
14515 border = 0;
14516 if (border < 0)
14517 border = 0;
14518
14519 rows = f->n_tab_bar_rows;
14520 height = max (1, (it.last_visible_y - border) / rows);
14521 extra = it.last_visible_y - border - height * rows;
14522
14523 while (it.current_y < it.last_visible_y)
14524 {
14525 int h = 0;
14526 if (extra > 0 && rows-- > 0)
14527 {
14528 h = (extra + rows - 1) / rows;
14529 extra -= h;
14530 }
14531 display_tab_bar_line (&it, height + h);
14532 }
14533 }
14534 else
14535 {
14536 while (it.current_y < it.last_visible_y)
14537 display_tab_bar_line (&it, 0);
14538 }
14539
14540
14541
14542 w->desired_matrix->no_scrolling_p = true;
14543 w->must_be_updated_p = true;
14544
14545 if (!NILP (Vauto_resize_tab_bars))
14546 {
14547 bool change_height_p = false;
14548
14549
14550
14551 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14552 change_height_p = true;
14553
14554
14555
14556
14557
14558 row = it.glyph_row - 1;
14559
14560
14561
14562
14563 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14564 && row->height >= FRAME_LINE_HEIGHT (f))
14565 change_height_p = true;
14566
14567
14568
14569 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14570 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14571 change_height_p = true;
14572
14573
14574
14575 if (change_height_p)
14576 {
14577 int nrows;
14578 int new_height = tab_bar_height (f, &nrows, true);
14579
14580 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14581 && !f->minimize_tab_bar_window_p)
14582 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14583 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14584 f->minimize_tab_bar_window_p = false;
14585
14586 if (change_height_p)
14587 {
14588 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14589 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14590 frame_default_tab_bar_height = new_height;
14591 clear_glyph_matrix (w->desired_matrix);
14592 f->n_tab_bar_rows = nrows;
14593 f->fonts_changed = true;
14594
14595 return true;
14596 }
14597 }
14598 }
14599
14600 f->minimize_tab_bar_window_p = false;
14601 return false;
14602 }
14603
14604
14605
14606
14607
14608
14609
14610 static bool
14611 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14612 int *prop_idx, bool *close_p)
14613 {
14614 Lisp_Object prop;
14615 ptrdiff_t charpos;
14616
14617
14618
14619
14620 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14621 charpos = max (0, charpos);
14622
14623
14624
14625
14626 prop = Fget_text_property (make_fixnum (charpos),
14627 Qmenu_item, f->current_tab_bar_string);
14628 if (! FIXNUMP (prop))
14629 return false;
14630 *prop_idx = XFIXNUM (prop);
14631
14632 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14633 Qclose_tab,
14634 f->current_tab_bar_string));
14635
14636 return true;
14637 }
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650 static int
14651 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14652 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14653 {
14654 struct window *w = XWINDOW (f->tab_bar_window);
14655 int area;
14656
14657
14658 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14659 if (*glyph == NULL)
14660 return -1;
14661
14662
14663
14664 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14665 return -1;
14666
14667 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14668 }
14669
14670
14671
14672
14673
14674
14675
14676
14677 Lisp_Object
14678 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14679 int modifiers)
14680 {
14681 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14682 struct window *w = XWINDOW (f->tab_bar_window);
14683 int hpos, vpos, prop_idx;
14684 bool close_p;
14685 struct glyph *glyph;
14686 Lisp_Object enabled_p;
14687 int ts;
14688
14689 frame_to_window_pixel_xy (w, &x, &y);
14690 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14691 if (ts == -1)
14692 return Fcons (Qtab_bar, Qnil);
14693
14694
14695 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14696 if (NILP (enabled_p))
14697 return Qnil;
14698
14699 if (down_p)
14700 {
14701
14702 if (!NILP (Vmouse_highlight))
14703 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14704 f->last_tab_bar_item = prop_idx;
14705 }
14706 else
14707 {
14708
14709 if (!NILP (Vmouse_highlight))
14710 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14711 f->last_tab_bar_item = -1;
14712 }
14713
14714 Lisp_Object caption =
14715 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14716
14717 AUTO_LIST2 (props, Qmenu_item,
14718 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14719 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14720 close_p ? Qt : Qnil));
14721
14722 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14723 props, caption);
14724
14725 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14726 }
14727
14728
14729
14730
14731
14732
14733 static void
14734 note_tab_bar_highlight (struct frame *f, int x, int y)
14735 {
14736 Lisp_Object window = f->tab_bar_window;
14737 struct window *w = XWINDOW (window);
14738 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14739 int hpos, vpos;
14740 struct glyph *glyph;
14741 struct glyph_row *row;
14742 int i;
14743 Lisp_Object enabled_p;
14744 int prop_idx;
14745 bool close_p;
14746 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14747 int rc;
14748
14749
14750
14751 if (x <= 0 || y <= 0)
14752 {
14753 clear_mouse_face (hlinfo);
14754 return;
14755 }
14756
14757 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14758 if (rc < 0)
14759 {
14760
14761 clear_mouse_face (hlinfo);
14762 return;
14763 }
14764 else if (rc == 0)
14765
14766 goto set_help_echo;
14767
14768 clear_mouse_face (hlinfo);
14769
14770 bool mouse_down_p = false;
14771
14772
14773
14774
14775
14776 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14777 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14778 && f == dpyinfo->last_mouse_frame);
14779
14780 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14781 && f->last_tab_bar_item != -1)
14782 return;
14783 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14784
14785
14786 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14787 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14788 {
14789
14790
14791 row = MATRIX_ROW (w->current_matrix, vpos);
14792 for (i = x = 0; i < hpos; ++i)
14793 x += row->glyphs[TEXT_AREA][i].pixel_width;
14794
14795
14796 hlinfo->mouse_face_beg_col = hpos;
14797 hlinfo->mouse_face_beg_row = vpos;
14798 hlinfo->mouse_face_beg_x = x;
14799 hlinfo->mouse_face_past_end = false;
14800
14801 hlinfo->mouse_face_end_col = hpos + 1;
14802 hlinfo->mouse_face_end_row = vpos;
14803 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14804 hlinfo->mouse_face_window = window;
14805 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14806
14807
14808 show_mouse_face (hlinfo, draw);
14809 }
14810
14811 set_help_echo:
14812
14813
14814
14815 help_echo_object = help_echo_window = Qnil;
14816 help_echo_pos = -1;
14817 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14818 if (NILP (help_echo_string))
14819 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14820 }
14821
14822 #endif
14823
14824
14825 static Lisp_Object
14826 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14827 {
14828 ptrdiff_t clen = 0;
14829
14830 for (int i = 0; i < f->n_tab_bar_items; i++)
14831 {
14832 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14833 + TAB_BAR_ITEM_CAPTION));
14834 if (NILP (caption))
14835 return Qnil;
14836 clen += SCHARS (caption);
14837 if (x < clen)
14838 {
14839 *prop_idx = i;
14840 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14841 - (clen - x)),
14842 Qclose_tab,
14843 caption));
14844 return caption;
14845 }
14846 }
14847 return Qnil;
14848 }
14849
14850
14851
14852
14853
14854
14855 Lisp_Object
14856 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14857 struct input_event *event)
14858 {
14859
14860 if (y < FRAME_MENU_BAR_LINES (f)
14861 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14862 return Qnil;
14863
14864
14865 int prop_idx;
14866 bool close_p;
14867 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14868
14869 if (NILP (caption))
14870 return Qnil;
14871
14872 if (NILP (AREF (f->tab_bar_items,
14873 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14874 return Qnil;
14875
14876 if (down_p)
14877 f->last_tab_bar_item = prop_idx;
14878 else
14879 f->last_tab_bar_item = -1;
14880
14881 caption = Fcopy_sequence (caption);
14882
14883 AUTO_LIST2 (props, Qmenu_item,
14884 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14885 + TAB_BAR_ITEM_KEY),
14886 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14887 + TAB_BAR_ITEM_BINDING),
14888 close_p ? Qt : Qnil));
14889
14890 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14891 props, caption);
14892
14893 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14894 }
14895
14896
14897
14898
14899
14900
14901
14902 #ifdef HAVE_WINDOW_SYSTEM
14903
14904
14905
14906
14907
14908
14909 static void
14910 update_tool_bar (struct frame *f, bool save_match_data)
14911 {
14912 #ifdef HAVE_EXT_TOOL_BAR
14913 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14914 #else
14915 bool do_update = (WINDOWP (f->tool_bar_window)
14916 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14917 #endif
14918
14919 if (do_update)
14920 {
14921 Lisp_Object window;
14922 struct window *w;
14923
14924 window = FRAME_SELECTED_WINDOW (f);
14925 w = XWINDOW (window);
14926
14927
14928
14929
14930
14931
14932
14933
14934 if (windows_or_buffers_changed
14935 || w->update_mode_line
14936 || update_mode_lines
14937 || window_buffer_changed (w))
14938 {
14939 struct buffer *prev = current_buffer;
14940 specpdl_ref count = SPECPDL_INDEX ();
14941 Lisp_Object frame, new_tool_bar;
14942 int new_n_tool_bar;
14943
14944
14945
14946
14947 set_buffer_internal_1 (XBUFFER (w->contents));
14948
14949
14950 if (save_match_data)
14951 record_unwind_save_match_data ();
14952
14953
14954 if (NILP (Voverriding_local_map_menu_flag))
14955 {
14956 specbind (Qoverriding_terminal_local_map, Qnil);
14957 specbind (Qoverriding_local_map, Qnil);
14958 }
14959
14960
14961
14962
14963
14964 eassert (EQ (selected_window,
14965
14966
14967 XFRAME (selected_frame)->selected_window));
14968 record_unwind_protect (restore_selected_window, selected_window);
14969 XSETFRAME (frame, f);
14970 selected_frame = frame;
14971 selected_window = FRAME_SELECTED_WINDOW (f);
14972
14973
14974 new_tool_bar
14975 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14976 &new_n_tool_bar);
14977
14978
14979 if (new_n_tool_bar != f->n_tool_bar_items
14980 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14981 {
14982
14983
14984
14985 block_input ();
14986 fset_tool_bar_items (f, new_tool_bar);
14987 f->n_tool_bar_items = new_n_tool_bar;
14988 w->update_mode_line = true;
14989 unblock_input ();
14990 }
14991
14992 unbind_to (count, Qnil);
14993 set_buffer_internal_1 (prev);
14994 }
14995 }
14996 }
14997
14998 #ifndef HAVE_EXT_TOOL_BAR
14999
15000
15001
15002
15003
15004 static void
15005 build_desired_tool_bar_string (struct frame *f)
15006 {
15007 int i, size, size_needed;
15008 Lisp_Object image, plist;
15009
15010 image = plist = Qnil;
15011
15012
15013
15014
15015
15016 size = (STRINGP (f->desired_tool_bar_string)
15017 ? SCHARS (f->desired_tool_bar_string)
15018 : 0);
15019
15020
15021 size_needed = f->n_tool_bar_items;
15022
15023
15024 if (size < size_needed || NILP (f->desired_tool_bar_string))
15025 fset_desired_tool_bar_string
15026 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil));
15027 else
15028 {
15029 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15030 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15031 props, f->desired_tool_bar_string);
15032 }
15033
15034
15035
15036
15037 for (i = 0; i < f->n_tool_bar_items; ++i)
15038 {
15039 #define PROP(IDX) \
15040 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15041
15042 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15043 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15044 int hmargin, vmargin, relief, idx, end;
15045
15046
15047
15048 image = PROP (TOOL_BAR_ITEM_IMAGES);
15049 if (VECTORP (image))
15050 {
15051 if (enabled_p)
15052 idx = (selected_p
15053 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15054 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15055 else
15056 idx = (selected_p
15057 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15058 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15059
15060 eassert (ASIZE (image) >= idx);
15061 image = AREF (image, idx);
15062 }
15063 else
15064 idx = -1;
15065
15066
15067 if (!valid_image_p (image))
15068 continue;
15069
15070
15071 plist = Fcopy_sequence (XCDR (image));
15072
15073
15074 relief = (tool_bar_button_relief >= 0
15075 ? min (tool_bar_button_relief,
15076 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15077 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15078 hmargin = vmargin = relief;
15079
15080 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15081 INT_MAX - max (hmargin, vmargin)))
15082 {
15083 hmargin += XFIXNAT (Vtool_bar_button_margin);
15084 vmargin += XFIXNAT (Vtool_bar_button_margin);
15085 }
15086 else if (CONSP (Vtool_bar_button_margin))
15087 {
15088 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15089 INT_MAX - hmargin))
15090 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15091
15092 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15093 INT_MAX - vmargin))
15094 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15095 }
15096
15097 if (auto_raise_tool_bar_buttons_p)
15098 {
15099
15100
15101 if (selected_p)
15102 {
15103 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15104 hmargin -= relief;
15105 vmargin -= relief;
15106 }
15107 }
15108 else
15109 {
15110
15111
15112
15113 plist = plist_put (plist, QCrelief,
15114 (selected_p
15115 ? make_fixnum (-relief)
15116 : make_fixnum (relief)));
15117 hmargin -= relief;
15118 vmargin -= relief;
15119 }
15120
15121
15122 if (hmargin || vmargin)
15123 {
15124 if (hmargin == vmargin)
15125 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15126 else
15127 plist = plist_put (plist, QCmargin,
15128 Fcons (make_fixnum (hmargin),
15129 make_fixnum (vmargin)));
15130 }
15131
15132
15133
15134
15135 if (!enabled_p && idx < 0)
15136 plist = plist_put (plist, QCconversion, Qdisabled);
15137
15138
15139
15140
15141
15142 image = Fcons (Qimage, plist);
15143 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15144 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15145
15146
15147
15148
15149 if (i + 1 == f->n_tool_bar_items)
15150 end = SCHARS (f->desired_tool_bar_string);
15151 else
15152 end = i + 1;
15153 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15154 props, f->desired_tool_bar_string);
15155 #undef PROP
15156 }
15157 }
15158
15159
15160
15161
15162
15163
15164
15165
15166
15167
15168
15169
15170
15171
15172 static void
15173 display_tool_bar_line (struct it *it, int height)
15174 {
15175 struct glyph_row *row = it->glyph_row;
15176 int max_x = it->last_visible_x;
15177 struct glyph *last;
15178
15179
15180 clear_glyph_row (row);
15181 row->enabled_p = true;
15182 row->y = it->current_y;
15183
15184
15185
15186 it->start_of_box_run_p = true;
15187
15188 while (it->current_x < max_x)
15189 {
15190 int x, n_glyphs_before, i, nglyphs;
15191 struct it it_before;
15192
15193
15194 if (!get_next_display_element (it))
15195 {
15196
15197 if (height < 0 && !it->hpos)
15198 return;
15199 break;
15200 }
15201
15202
15203 n_glyphs_before = row->used[TEXT_AREA];
15204 it_before = *it;
15205
15206 PRODUCE_GLYPHS (it);
15207
15208 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15209 i = 0;
15210 x = it_before.current_x;
15211 while (i < nglyphs)
15212 {
15213 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15214
15215 if (x + glyph->pixel_width > max_x)
15216 {
15217
15218 row->used[TEXT_AREA] = n_glyphs_before;
15219 *it = it_before;
15220
15221
15222
15223 if (n_glyphs_before == 0
15224 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15225 break;
15226 goto out;
15227 }
15228
15229 ++it->hpos;
15230 x += glyph->pixel_width;
15231 ++i;
15232 }
15233
15234
15235 if (ITERATOR_AT_END_OF_LINE_P (it))
15236 break;
15237
15238 set_iterator_to_next (it, true);
15239 }
15240
15241 out:;
15242
15243 row->displays_text_p = row->used[TEXT_AREA] != 0;
15244
15245
15246
15247
15248
15249
15250
15251 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15252 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15253 it->face_id = DEFAULT_FACE_ID;
15254
15255 extend_face_to_end_of_line (it);
15256 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15257 last->right_box_line_p = true;
15258 if (last == row->glyphs[TEXT_AREA])
15259 last->left_box_line_p = true;
15260
15261
15262 if ((height -= it->max_ascent + it->max_descent) > 0)
15263 {
15264
15265 height %= FRAME_LINE_HEIGHT (it->f);
15266 it->max_ascent += height / 2;
15267 it->max_descent += (height + 1) / 2;
15268 }
15269
15270 compute_line_metrics (it);
15271
15272
15273 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15274 {
15275 row->height = row->phys_height = it->last_visible_y - row->y;
15276 row->visible_height = row->height;
15277 row->ascent = row->phys_ascent = 0;
15278 row->extra_line_spacing = 0;
15279 }
15280
15281 row->full_width_p = true;
15282 row->continued_p = false;
15283 row->truncated_on_left_p = false;
15284 row->truncated_on_right_p = false;
15285
15286 it->current_x = it->hpos = 0;
15287 it->current_y += row->height;
15288 ++it->vpos;
15289 ++it->glyph_row;
15290 }
15291
15292
15293
15294
15295
15296 static int
15297 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15298 {
15299 struct window *w = XWINDOW (f->tool_bar_window);
15300 struct it it;
15301
15302
15303
15304 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15305
15306
15307
15308 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15309 temp_row->reversed_p = false;
15310 it.first_visible_x = 0;
15311 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15312 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15313 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15314 it.paragraph_embedding = L2R;
15315
15316 while (!ITERATOR_AT_END_P (&it))
15317 {
15318 clear_glyph_row (temp_row);
15319 it.glyph_row = temp_row;
15320 display_tool_bar_line (&it, -1);
15321 }
15322 clear_glyph_row (temp_row);
15323
15324
15325 if (n_rows)
15326 *n_rows = it.vpos > 0 ? it.vpos : -1;
15327
15328 if (pixelwise)
15329 return it.current_y;
15330 else
15331 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15332 }
15333
15334 #endif
15335
15336 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15337 0, 2, 0,
15338 doc:
15339
15340 )
15341 (Lisp_Object frame, Lisp_Object pixelwise)
15342 {
15343 int height = 0;
15344
15345 #ifndef HAVE_EXT_TOOL_BAR
15346 struct frame *f = decode_any_frame (frame);
15347
15348 if (WINDOWP (f->tool_bar_window)
15349 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15350 {
15351 update_tool_bar (f, true);
15352 if (f->n_tool_bar_items)
15353 {
15354 build_desired_tool_bar_string (f);
15355 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15356 }
15357 }
15358 #endif
15359
15360 return make_fixnum (height);
15361 }
15362
15363 #ifndef HAVE_EXT_TOOL_BAR
15364
15365
15366
15367 static bool
15368 redisplay_tool_bar (struct frame *f)
15369 {
15370 struct window *w;
15371 struct it it;
15372 struct glyph_row *row;
15373
15374 f->tool_bar_redisplayed = true;
15375
15376
15377
15378
15379
15380 if (!WINDOWP (f->tool_bar_window)
15381 || (w = XWINDOW (f->tool_bar_window),
15382 WINDOW_TOTAL_LINES (w) == 0))
15383 {
15384
15385
15386
15387
15388
15389 f->tool_bar_resized = true;
15390
15391 return false;
15392 }
15393
15394
15395 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15396 it.first_visible_x = 0;
15397 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15398 row = it.glyph_row;
15399 row->reversed_p = false;
15400
15401
15402 build_desired_tool_bar_string (f);
15403 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15404 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15405
15406
15407
15408
15409
15410
15411
15412 it.paragraph_embedding = L2R;
15413
15414 if (f->n_tool_bar_rows == 0)
15415 {
15416 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15417
15418 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15419 {
15420 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15421 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15422 frame_default_tool_bar_height = new_height;
15423
15424 clear_glyph_matrix (w->desired_matrix);
15425 f->fonts_changed = true;
15426 return true;
15427 }
15428 }
15429
15430
15431
15432 if (f->n_tool_bar_rows > 0)
15433 {
15434 int border, rows, height, extra;
15435
15436 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15437 border = XFIXNUM (Vtool_bar_border);
15438 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15439 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15440 else if (EQ (Vtool_bar_border, Qborder_width))
15441 border = f->border_width;
15442 else
15443 border = 0;
15444 if (border < 0)
15445 border = 0;
15446
15447 rows = f->n_tool_bar_rows;
15448 height = max (1, (it.last_visible_y - border) / rows);
15449 extra = it.last_visible_y - border - height * rows;
15450
15451 while (it.current_y < it.last_visible_y)
15452 {
15453 int h = 0;
15454 if (extra > 0 && rows-- > 0)
15455 {
15456 h = (extra + rows - 1) / rows;
15457 extra -= h;
15458 }
15459 display_tool_bar_line (&it, height + h);
15460 }
15461 }
15462 else
15463 {
15464 while (it.current_y < it.last_visible_y)
15465 display_tool_bar_line (&it, 0);
15466 }
15467
15468
15469
15470 w->desired_matrix->no_scrolling_p = true;
15471 w->must_be_updated_p = true;
15472
15473 if (!NILP (Vauto_resize_tool_bars))
15474 {
15475 bool change_height_p = false;
15476
15477
15478
15479 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15480 change_height_p = true;
15481
15482
15483
15484
15485
15486 row = it.glyph_row - 1;
15487
15488
15489
15490
15491 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15492 && row->height >= FRAME_LINE_HEIGHT (f))
15493 change_height_p = true;
15494
15495
15496
15497 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15498 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15499 change_height_p = true;
15500
15501
15502
15503 if (change_height_p)
15504 {
15505 int nrows;
15506 int new_height = tool_bar_height (f, &nrows, true);
15507
15508 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15509 && !f->minimize_tool_bar_window_p)
15510 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15511 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15512 f->minimize_tool_bar_window_p = false;
15513
15514 if (change_height_p)
15515 {
15516 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15517 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15518 frame_default_tool_bar_height = new_height;
15519 clear_glyph_matrix (w->desired_matrix);
15520 f->n_tool_bar_rows = nrows;
15521 f->fonts_changed = true;
15522
15523 return true;
15524 }
15525 }
15526 }
15527
15528 f->minimize_tool_bar_window_p = false;
15529
15530 return false;
15531 }
15532
15533
15534
15535
15536
15537
15538 static bool
15539 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15540 {
15541 Lisp_Object prop;
15542 ptrdiff_t charpos;
15543
15544
15545
15546
15547 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15548 charpos = max (0, charpos);
15549
15550
15551
15552
15553 prop = Fget_text_property (make_fixnum (charpos),
15554 Qmenu_item, f->current_tool_bar_string);
15555 if (! FIXNUMP (prop))
15556 return false;
15557 *prop_idx = XFIXNUM (prop);
15558 return true;
15559 }
15560
15561
15562
15563
15564
15565
15566
15567
15568
15569
15570
15571
15572 static int
15573 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15574 int *hpos, int *vpos, int *prop_idx)
15575 {
15576 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15577 struct window *w = XWINDOW (f->tool_bar_window);
15578 int area;
15579
15580
15581 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15582 if (*glyph == NULL)
15583 return -1;
15584
15585
15586
15587 if (!tool_bar_item_info (f, *glyph, prop_idx))
15588 return -1;
15589
15590
15591 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15592 && *vpos >= hlinfo->mouse_face_beg_row
15593 && *vpos <= hlinfo->mouse_face_end_row
15594 && (*vpos > hlinfo->mouse_face_beg_row
15595 || *hpos >= hlinfo->mouse_face_beg_col)
15596 && (*vpos < hlinfo->mouse_face_end_row
15597 || *hpos < hlinfo->mouse_face_end_col
15598 || hlinfo->mouse_face_past_end))
15599 return 0;
15600
15601 return 1;
15602 }
15603
15604
15605
15606
15607
15608
15609
15610
15611 void
15612 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15613 int modifiers, Lisp_Object device)
15614 {
15615 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15616 struct window *w = XWINDOW (f->tool_bar_window);
15617 int hpos, vpos, prop_idx;
15618 struct glyph *glyph;
15619 Lisp_Object enabled_p;
15620 int ts;
15621
15622
15623
15624
15625
15626
15627
15628
15629 frame_to_window_pixel_xy (w, &x, &y);
15630 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15631 if (ts == -1
15632 || (ts != 0 && !NILP (Vmouse_highlight)))
15633 return;
15634
15635
15636
15637
15638 if (NILP (Vmouse_highlight) && !down_p)
15639 prop_idx = f->last_tool_bar_item;
15640
15641
15642 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15643 if (NILP (enabled_p))
15644 return;
15645
15646 if (down_p)
15647 {
15648
15649 if (!NILP (Vmouse_highlight))
15650 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15651 f->last_tool_bar_item = prop_idx;
15652 }
15653 else
15654 {
15655 Lisp_Object key, frame;
15656 struct input_event event;
15657 EVENT_INIT (event);
15658
15659
15660 if (!NILP (Vmouse_highlight))
15661 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15662
15663 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15664
15665 XSETFRAME (frame, f);
15666 event.kind = TOOL_BAR_EVENT;
15667 event.frame_or_window = frame;
15668 event.arg = key;
15669 event.modifiers = modifiers;
15670 event.device = device;
15671 kbd_buffer_store_event (&event);
15672 f->last_tool_bar_item = -1;
15673 }
15674 }
15675
15676 void
15677 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15678 int modifiers)
15679 {
15680 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15681 }
15682
15683
15684
15685
15686
15687 static void
15688 note_tool_bar_highlight (struct frame *f, int x, int y)
15689 {
15690 Lisp_Object window = f->tool_bar_window;
15691 struct window *w = XWINDOW (window);
15692 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15693 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15694 int hpos, vpos;
15695 struct glyph *glyph;
15696 struct glyph_row *row;
15697 int i;
15698 Lisp_Object enabled_p;
15699 int prop_idx;
15700 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15701 bool mouse_down_p;
15702 int rc;
15703
15704
15705
15706 if (x <= 0 || y <= 0)
15707 {
15708 clear_mouse_face (hlinfo);
15709 return;
15710 }
15711
15712 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15713 if (rc < 0)
15714 {
15715
15716 clear_mouse_face (hlinfo);
15717 return;
15718 }
15719 else if (rc == 0)
15720
15721 goto set_help_echo;
15722
15723 clear_mouse_face (hlinfo);
15724
15725
15726 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15727 && f == dpyinfo->last_mouse_frame);
15728
15729 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15730 return;
15731
15732 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15733
15734
15735 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15736 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15737 {
15738
15739
15740 row = MATRIX_ROW (w->current_matrix, vpos);
15741 for (i = x = 0; i < hpos; ++i)
15742 x += row->glyphs[TEXT_AREA][i].pixel_width;
15743
15744
15745 hlinfo->mouse_face_beg_col = hpos;
15746 hlinfo->mouse_face_beg_row = vpos;
15747 hlinfo->mouse_face_beg_x = x;
15748 hlinfo->mouse_face_past_end = false;
15749
15750 hlinfo->mouse_face_end_col = hpos + 1;
15751 hlinfo->mouse_face_end_row = vpos;
15752 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15753 hlinfo->mouse_face_window = window;
15754 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15755
15756
15757 show_mouse_face (hlinfo, draw);
15758 }
15759
15760 set_help_echo:
15761
15762
15763
15764 help_echo_object = help_echo_window = Qnil;
15765 help_echo_pos = -1;
15766 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15767 if (NILP (help_echo_string))
15768 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15769 }
15770
15771 #endif
15772
15773 #endif
15774
15775
15776
15777
15778
15779
15780
15781
15782
15783
15784
15785
15786
15787 static bool
15788 hscroll_window_tree (Lisp_Object window)
15789 {
15790 bool hscrolled_p = false;
15791 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15792 int hscroll_step_abs = 0;
15793 double hscroll_step_rel = 0;
15794
15795 if (hscroll_relative_p)
15796 {
15797 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15798 if (hscroll_step_rel < 0)
15799 {
15800 hscroll_relative_p = false;
15801 hscroll_step_abs = 0;
15802 }
15803 }
15804 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15805 {
15806 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15807 if (hscroll_step_abs < 0)
15808 hscroll_step_abs = 0;
15809 }
15810 else
15811 hscroll_step_abs = 0;
15812
15813 while (WINDOWP (window))
15814 {
15815 struct window *w = XWINDOW (window);
15816
15817 if (WINDOWP (w->contents))
15818 hscrolled_p |= hscroll_window_tree (w->contents);
15819 else if (w->cursor.vpos >= 0
15820
15821
15822
15823
15824
15825
15826 && !(w == XWINDOW (echo_area_window)
15827 && !NILP (echo_area_buffer[0])))
15828 {
15829 int h_margin;
15830 int text_area_width;
15831 struct glyph_row *cursor_row;
15832 struct glyph_row *bottom_row;
15833
15834 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15835 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15836 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15837 else
15838 cursor_row = bottom_row - 1;
15839
15840 if (!cursor_row->enabled_p)
15841 {
15842 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15843 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15844 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15845 else
15846 cursor_row = bottom_row - 1;
15847 }
15848 bool row_r2l_p = cursor_row->reversed_p;
15849 bool hscl = hscrolling_current_line_p (w);
15850 int x_offset = 0;
15851
15852
15853 if (!NILP (Vdisplay_line_numbers))
15854 {
15855 struct glyph *g;
15856 if (!row_r2l_p)
15857 {
15858 for (g = cursor_row->glyphs[TEXT_AREA];
15859 g < cursor_row->glyphs[TEXT_AREA]
15860 + cursor_row->used[TEXT_AREA];
15861 g++)
15862 {
15863 if (!(NILP (g->object) && g->charpos < 0))
15864 break;
15865 x_offset += g->pixel_width;
15866 }
15867 }
15868 else
15869 {
15870 for (g = cursor_row->glyphs[TEXT_AREA]
15871 + cursor_row->used[TEXT_AREA];
15872 g > cursor_row->glyphs[TEXT_AREA];
15873 g--)
15874 {
15875 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15876 break;
15877 x_offset += (g - 1)->pixel_width;
15878 }
15879 }
15880 }
15881 if (cursor_row->truncated_on_left_p)
15882 {
15883
15884 struct frame *f = XFRAME (WINDOW_FRAME (w));
15885 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15886 }
15887
15888 text_area_width = window_box_width (w, TEXT_AREA);
15889
15890
15891 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15892 * WINDOW_FRAME_COLUMN_WIDTH (w));
15893
15894
15895
15896 if (w->suspend_auto_hscroll
15897 && NILP (Fequal (Fwindow_point (window),
15898 Fwindow_old_point (window))))
15899 {
15900 w->suspend_auto_hscroll = false;
15901
15902
15903
15904
15905 if (w->min_hscroll == 0 && w->hscroll > 0
15906 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15907 Qcurrent_line))
15908 SET_FRAME_GARBAGED (XFRAME (w->frame));
15909 }
15910
15911
15912 Fset_marker (w->old_pointm,
15913 ((w == XWINDOW (selected_window))
15914 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15915 : Fmarker_position (w->pointm)),
15916 w->contents);
15917
15918 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15919 && !w->suspend_auto_hscroll
15920
15921
15922
15923
15924
15925
15926 && (CHARPOS (cursor_row->start.pos)
15927 >= BUF_BEG (XBUFFER (w->contents)))
15928
15929
15930
15931
15932 && ((!row_r2l_p
15933 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
15934 || (cursor_row->enabled_p
15935 && cursor_row->truncated_on_right_p
15936 && (w->cursor.x >= text_area_width - h_margin))))
15937
15938
15939
15940
15941
15942
15943 || (row_r2l_p
15944 && ((cursor_row->enabled_p
15945
15946
15947
15948 && cursor_row->truncated_on_right_p
15949 && w->cursor.x <= h_margin)
15950 || (w->hscroll
15951 && (w->cursor.x >= (text_area_width - h_margin
15952 - x_offset)))))
15953
15954
15955
15956
15957
15958 || (hscl
15959 && w->hscroll != w->min_hscroll
15960 && !cursor_row->truncated_on_left_p)))
15961 {
15962 struct it it;
15963 ptrdiff_t hscroll;
15964 struct buffer *saved_current_buffer;
15965 ptrdiff_t pt;
15966 int wanted_x;
15967
15968
15969 saved_current_buffer = current_buffer;
15970 current_buffer = XBUFFER (w->contents);
15971
15972 if (w == XWINDOW (selected_window))
15973 pt = PT;
15974 else
15975 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
15976
15977
15978
15979 init_to_row_start (&it, w, cursor_row);
15980 if (hscl)
15981 it.first_visible_x = window_hscroll_limited (w, it.f)
15982 * FRAME_COLUMN_WIDTH (it.f);
15983 it.last_visible_x = DISP_INFINITY;
15984
15985 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15986 if (current_buffer->long_line_optimizations_p
15987 && nchars > large_hscroll_threshold)
15988 {
15989
15990
15991
15992
15993 fast_move_it_horizontally (&it, nchars);
15994 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15995 }
15996 else
15997 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15998
15999
16000
16001
16002
16003
16004 if (it.method == GET_FROM_STRING && pt > 1)
16005 {
16006 init_to_row_start (&it, w, cursor_row);
16007 if (hscl)
16008 it.first_visible_x = (window_hscroll_limited (w, it.f)
16009 * FRAME_COLUMN_WIDTH (it.f));
16010 if (current_buffer->long_line_optimizations_p
16011 && nchars > large_hscroll_threshold)
16012 {
16013 fast_move_it_horizontally (&it, nchars - 1);
16014 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16015 }
16016 else
16017 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16018 }
16019 current_buffer = saved_current_buffer;
16020
16021
16022 if (!hscroll_relative_p && hscroll_step_abs == 0)
16023 hscroll = max (0, (it.current_x
16024 - (ITERATOR_AT_END_OF_LINE_P (&it)
16025 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16026 : (text_area_width / 2))))
16027 / FRAME_COLUMN_WIDTH (it.f);
16028 else if ((!row_r2l_p
16029 && w->cursor.x >= text_area_width - h_margin)
16030 || (row_r2l_p && w->cursor.x <= h_margin))
16031 {
16032 if (hscroll_relative_p)
16033 wanted_x = text_area_width * (1 - hscroll_step_rel)
16034 - h_margin;
16035 else
16036 wanted_x = text_area_width
16037 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16038 - h_margin;
16039 hscroll
16040 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16041 }
16042 else
16043 {
16044 if (hscroll_relative_p)
16045 wanted_x =
16046 text_area_width * hscroll_step_rel + h_margin + x_offset;
16047 else
16048 wanted_x =
16049 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16050 + h_margin + x_offset;
16051 hscroll
16052 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16053 }
16054 hscroll = max (hscroll, w->min_hscroll);
16055
16056
16057
16058
16059 if (w->hscroll != hscroll
16060
16061
16062
16063
16064 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16065 {
16066 struct buffer *b = XBUFFER (w->contents);
16067 b->prevent_redisplay_optimizations_p = true;
16068 w->hscroll = hscroll;
16069 hscrolled_p = true;
16070 }
16071 }
16072 }
16073
16074 window = w->next;
16075 }
16076
16077
16078 return hscrolled_p;
16079 }
16080
16081
16082
16083
16084
16085
16086
16087
16088 static bool
16089 hscroll_windows (Lisp_Object window)
16090 {
16091 bool hscrolled_p = hscroll_window_tree (window);
16092 if (hscrolled_p)
16093 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16094 return hscrolled_p;
16095 }
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106 #ifdef GLYPH_DEBUG
16107
16108
16109
16110 static int debug_first_unchanged_at_end_vpos;
16111 static int debug_last_unchanged_at_beg_vpos;
16112
16113
16114
16115 static int debug_dvpos, debug_dy;
16116
16117
16118
16119 static ptrdiff_t debug_delta, debug_delta_bytes;
16120
16121
16122
16123
16124 static ptrdiff_t debug_end_vpos;
16125
16126
16127
16128
16129
16130 static void debug_method_add (struct window *, char const *, ...)
16131 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16132
16133 static void
16134 debug_method_add (struct window *w, char const *fmt, ...)
16135 {
16136 void *ptr = w;
16137 char *method = w->desired_matrix->method;
16138 int len = strlen (method);
16139 int size = sizeof w->desired_matrix->method;
16140 int remaining = size - len - 1;
16141 va_list ap;
16142
16143 if (len && remaining)
16144 {
16145 method[len] = '|';
16146 --remaining, ++len;
16147 }
16148
16149 va_start (ap, fmt);
16150 vsnprintf (method + len, remaining + 1, fmt, ap);
16151 va_end (ap);
16152
16153 if (trace_redisplay_p)
16154 fprintf (stderr, "%p (%s): %s\n",
16155 ptr,
16156 ((BUFFERP (w->contents)
16157 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16158 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16159 : "no buffer"),
16160 method + len);
16161 }
16162
16163 #endif
16164
16165
16166
16167
16168
16169
16170
16171 static bool
16172 text_outside_line_unchanged_p (struct window *w,
16173 ptrdiff_t start, ptrdiff_t end)
16174 {
16175 bool unchanged_p = true;
16176
16177
16178 if (window_outdated (w))
16179 {
16180
16181 if (GPT < start || Z - GPT < end)
16182 unchanged_p = false;
16183
16184
16185 if (unchanged_p
16186 && (BEG_UNCHANGED < start - 1
16187 || END_UNCHANGED < end))
16188 unchanged_p = false;
16189
16190
16191
16192 if (unchanged_p
16193 && FIXNUMP (BVAR (current_buffer, selective_display))
16194 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16195 && (BEG_UNCHANGED < start || GPT <= start))
16196 unchanged_p = false;
16197
16198
16199
16200
16201
16202
16203
16204
16205 if (unchanged_p)
16206 {
16207 if (BEG + BEG_UNCHANGED == start
16208 && overlay_touches_p (start))
16209 unchanged_p = false;
16210 if (END_UNCHANGED == end
16211 && overlay_touches_p (Z - end))
16212 unchanged_p = false;
16213 }
16214
16215
16216
16217
16218
16219
16220
16221
16222 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16223 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16224 unchanged_p = false;
16225 }
16226
16227 return unchanged_p;
16228 }
16229
16230
16231
16232
16233
16234
16235
16236
16237
16238 void
16239 redisplay (void)
16240 {
16241 redisplay_internal ();
16242 }
16243
16244
16245 static Lisp_Object
16246 overlay_arrow_string_or_property (Lisp_Object var)
16247 {
16248 Lisp_Object val;
16249
16250 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16251 return val;
16252
16253 return Voverlay_arrow_string;
16254 }
16255
16256
16257 static bool
16258 overlay_arrow_in_current_buffer_p (void)
16259 {
16260 Lisp_Object vlist;
16261
16262 for (vlist = Voverlay_arrow_variable_list;
16263 CONSP (vlist);
16264 vlist = XCDR (vlist))
16265 {
16266 Lisp_Object var = XCAR (vlist);
16267 Lisp_Object val;
16268
16269 if (!SYMBOLP (var))
16270 continue;
16271 val = find_symbol_value (var);
16272 if (MARKERP (val)
16273 && current_buffer == XMARKER (val)->buffer)
16274 return true;
16275 }
16276 return false;
16277 }
16278
16279
16280
16281
16282
16283
16284
16285 static bool
16286 overlay_arrows_changed_p (bool set_redisplay)
16287 {
16288 Lisp_Object vlist;
16289 bool changed = false;
16290
16291 for (vlist = Voverlay_arrow_variable_list;
16292 CONSP (vlist);
16293 vlist = XCDR (vlist))
16294 {
16295 Lisp_Object var = XCAR (vlist);
16296 Lisp_Object val, pstr;
16297
16298 if (!SYMBOLP (var))
16299 continue;
16300 val = find_symbol_value (var);
16301 if (!MARKERP (val))
16302 continue;
16303 if (! EQ (Fmarker_position (val),
16304
16305
16306 Fget (var, Qlast_arrow_position))
16307 || ! (pstr = overlay_arrow_string_or_property (var),
16308 EQ (pstr, Fget (var, Qlast_arrow_string))))
16309 {
16310 struct buffer *buf = XMARKER (val)->buffer;
16311
16312 if (set_redisplay)
16313 {
16314 if (buf)
16315 bset_redisplay (buf);
16316 changed = true;
16317 }
16318 else
16319 return true;
16320 }
16321 }
16322 return changed;
16323 }
16324
16325
16326
16327 static void
16328 update_overlay_arrows (int up_to_date)
16329 {
16330 Lisp_Object vlist;
16331
16332 for (vlist = Voverlay_arrow_variable_list;
16333 CONSP (vlist);
16334 vlist = XCDR (vlist))
16335 {
16336 Lisp_Object var = XCAR (vlist);
16337
16338 if (!SYMBOLP (var))
16339 continue;
16340
16341 if (up_to_date > 0)
16342 {
16343 Lisp_Object val = find_symbol_value (var);
16344 if (!MARKERP (val))
16345 continue;
16346 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16347 Fput (var, Qlast_arrow_string,
16348 overlay_arrow_string_or_property (var));
16349 }
16350 else if (up_to_date < 0
16351 || !NILP (Fget (var, Qlast_arrow_position)))
16352 {
16353 Fput (var, Qlast_arrow_position, Qt);
16354 Fput (var, Qlast_arrow_string, Qt);
16355 }
16356 }
16357 }
16358
16359
16360
16361
16362
16363
16364 static Lisp_Object
16365 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16366 {
16367 Lisp_Object vlist;
16368
16369 for (vlist = Voverlay_arrow_variable_list;
16370 CONSP (vlist);
16371 vlist = XCDR (vlist))
16372 {
16373 Lisp_Object var = XCAR (vlist);
16374 Lisp_Object val;
16375
16376 if (!SYMBOLP (var))
16377 continue;
16378
16379 val = find_symbol_value (var);
16380
16381 if (MARKERP (val)
16382 && current_buffer == XMARKER (val)->buffer
16383 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16384 {
16385 if (FRAME_WINDOW_P (it->f)
16386
16387
16388 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16389 {
16390 #ifdef HAVE_WINDOW_SYSTEM
16391 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16392 {
16393 int fringe_bitmap = lookup_fringe_bitmap (val);
16394 if (fringe_bitmap != 0)
16395 return make_fixnum (fringe_bitmap);
16396 }
16397 #endif
16398 return make_fixnum (-1);
16399 }
16400 return overlay_arrow_string_or_property (var);
16401 }
16402 }
16403
16404 return Qnil;
16405 }
16406
16407
16408
16409
16410
16411 static bool
16412 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16413 struct buffer *buf, ptrdiff_t pt)
16414 {
16415 ptrdiff_t start, end;
16416 Lisp_Object prop;
16417 Lisp_Object buffer;
16418
16419 XSETBUFFER (buffer, buf);
16420
16421
16422 if (prev_buf == buf)
16423 {
16424 if (prev_pt == pt)
16425
16426 return false;
16427
16428 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16429 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16430 && composition_valid_p (start, end, prop)
16431 && start < prev_pt && end > prev_pt)
16432
16433
16434 return (pt <= start || pt >= end);
16435 }
16436
16437
16438 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16439 && find_composition (pt, -1, &start, &end, &prop, buffer)
16440 && composition_valid_p (start, end, prop)
16441 && start < pt && end > pt);
16442 }
16443
16444
16445
16446 static void
16447 reconsider_clip_changes (struct window *w)
16448 {
16449 struct buffer *b = XBUFFER (w->contents);
16450
16451 if (b->clip_changed
16452 && w->window_end_valid
16453 && w->current_matrix->buffer == b
16454 && w->current_matrix->zv == BUF_ZV (b)
16455 && w->current_matrix->begv == BUF_BEGV (b))
16456 b->clip_changed = false;
16457
16458
16459
16460
16461
16462 if (!b->clip_changed && w->window_end_valid)
16463 {
16464 ptrdiff_t pt = (w == XWINDOW (selected_window)
16465 ? PT : marker_position (w->pointm));
16466
16467 if ((w->current_matrix->buffer != b || pt != w->last_point)
16468 && check_point_in_composition (w->current_matrix->buffer,
16469 w->last_point, b, pt))
16470 b->clip_changed = true;
16471 }
16472 }
16473
16474 static void
16475 propagate_buffer_redisplay (void)
16476 {
16477
16478
16479
16480
16481
16482
16483
16484
16485
16486 Lisp_Object ws = window_list ();
16487 for (; CONSP (ws); ws = XCDR (ws))
16488 {
16489 struct window *thisw = XWINDOW (XCAR (ws));
16490 struct buffer *thisb = XBUFFER (thisw->contents);
16491 if (thisb->text->redisplay)
16492 thisw->redisplay = true;
16493 }
16494 }
16495
16496 #define STOP_POLLING \
16497 do { if (! polling_stopped_here) stop_polling (); \
16498 polling_stopped_here = true; } while (false)
16499
16500 #define RESUME_POLLING \
16501 do { if (polling_stopped_here) start_polling (); \
16502 polling_stopped_here = false; } while (false)
16503
16504
16505
16506
16507 static void
16508 redisplay_internal (void)
16509 {
16510 struct window *w = XWINDOW (selected_window);
16511 struct window *sw;
16512 struct frame *fr;
16513 bool pending;
16514 bool must_finish = false, match_p;
16515 struct text_pos tlbufpos, tlendpos;
16516 int number_of_visible_frames;
16517 struct frame *sf;
16518 bool polling_stopped_here = false;
16519 Lisp_Object tail, frame;
16520
16521
16522
16523
16524 enum { MAX_HSCROLL_RETRIES = 16 };
16525 int hscroll_retries = 0;
16526
16527
16528
16529
16530
16531
16532 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16533 int garbaged_frame_retries = 0;
16534
16535
16536
16537
16538 bool consider_all_windows_p;
16539
16540
16541 bool update_miniwindow_p = false;
16542
16543 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16544
16545
16546
16547
16548 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16549 && redisplay_skip_initial_frame)
16550 || !NILP (Vinhibit_redisplay))
16551 return;
16552
16553
16554
16555
16556 fr = XFRAME (w->frame);
16557 sf = SELECTED_FRAME ();
16558
16559 if (!fr->glyphs_initialized_p)
16560 return;
16561
16562 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16563 if (popup_activated ())
16564 return;
16565 #endif
16566
16567 #if defined (HAVE_HAIKU)
16568 if (popup_activated_p)
16569 return;
16570 #endif
16571
16572
16573 if (redisplaying_p)
16574 return;
16575
16576
16577
16578 specpdl_ref count = SPECPDL_INDEX ();
16579 record_unwind_protect_void (unwind_redisplay);
16580 redisplaying_p = true;
16581 block_buffer_flips ();
16582 specbind (Qinhibit_free_realized_faces, Qnil);
16583
16584
16585 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16586
16587 FOR_EACH_FRAME (tail, frame)
16588 XFRAME (frame)->already_hscrolled_p = false;
16589
16590 reset_outermost_restrictions ();
16591
16592 retry:
16593
16594 sw = w;
16595
16596 pending = false;
16597 forget_escape_and_glyphless_faces ();
16598
16599 inhibit_free_realized_faces = false;
16600
16601
16602
16603
16604 if (face_change)
16605 windows_or_buffers_changed = 47;
16606
16607 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16608 && FRAME_TTY (sf)->previous_frame != sf)
16609 {
16610
16611
16612
16613 SET_FRAME_GARBAGED (sf);
16614 #ifndef DOS_NT
16615 set_tty_color_mode (FRAME_TTY (sf), sf);
16616 #endif
16617 FRAME_TTY (sf)->previous_frame = sf;
16618 }
16619
16620
16621
16622
16623 number_of_visible_frames = 0;
16624
16625 FOR_EACH_FRAME (tail, frame)
16626 {
16627 struct frame *f = XFRAME (frame);
16628
16629 if (FRAME_REDISPLAY_P (f))
16630 {
16631 ++number_of_visible_frames;
16632
16633 if (f->fonts_changed)
16634 {
16635 adjust_frame_glyphs (f);
16636
16637
16638
16639
16640
16641
16642 SET_FRAME_GARBAGED (f);
16643 f->fonts_changed = false;
16644 }
16645
16646
16647 if (f != sf && f->cursor_type_changed)
16648 fset_redisplay (f);
16649 }
16650 clear_desired_matrices (f);
16651 }
16652
16653
16654 do_pending_window_change (true);
16655
16656
16657 clear_garbaged_frames ();
16658
16659
16660 if (NILP (Vmemory_full))
16661 prepare_menu_bars ();
16662
16663
16664
16665
16666
16667 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16668 sw = w;
16669
16670 reconsider_clip_changes (w);
16671
16672
16673 match_p = XBUFFER (w->contents) == current_buffer;
16674 if (match_p)
16675 {
16676
16677 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16678 w->update_mode_line = true;
16679
16680 if (mode_line_update_needed (w))
16681 w->update_mode_line = true;
16682
16683
16684
16685
16686 if (current_buffer->clip_changed)
16687 bset_update_mode_line (current_buffer);
16688 }
16689
16690
16691
16692
16693
16694
16695 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16696 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16697 || (message_cleared_p
16698 && minibuf_level == 0
16699
16700
16701 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16702 {
16703 echo_area_display (false);
16704
16705 if (message_cleared_p)
16706 update_miniwindow_p = true;
16707
16708 must_finish = true;
16709
16710
16711
16712
16713
16714 if (!display_last_displayed_message_p)
16715 message_cleared_p = false;
16716 }
16717 else if (EQ (selected_window, minibuf_window)
16718 && (current_buffer->clip_changed || window_outdated (w))
16719 && resize_mini_window (w, false))
16720 {
16721
16722
16723 must_finish = true;
16724
16725
16726
16727
16728 clear_garbaged_frames ();
16729 }
16730
16731 if (!NILP (Vrun_hooks))
16732 run_window_change_functions ();
16733
16734 if (windows_or_buffers_changed && !update_mode_lines)
16735
16736
16737
16738 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16739 ? REDISPLAY_SOME : 32);
16740
16741
16742
16743
16744
16745 overlay_arrows_changed_p (true);
16746
16747 consider_all_windows_p = (update_mode_lines
16748 || windows_or_buffers_changed);
16749
16750 #define AINC(a,i) \
16751 { \
16752 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16753 if (FIXNUMP (entry)) \
16754 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16755 }
16756
16757 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16758 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16759
16760
16761
16762
16763
16764 tlbufpos = this_line_start_pos;
16765 tlendpos = this_line_end_pos;
16766 if (!consider_all_windows_p
16767 && CHARPOS (tlbufpos) > 0
16768 && !w->update_mode_line
16769 && !current_buffer->clip_changed
16770 && !current_buffer->prevent_redisplay_optimizations_p
16771 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16772 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16773 && !XFRAME (w->frame)->cursor_type_changed
16774 && !XFRAME (w->frame)->face_change
16775
16776 && this_line_buffer == current_buffer
16777 && match_p
16778 && !w->force_start
16779 && !w->optional_new_start
16780
16781 && PT >= CHARPOS (tlbufpos)
16782 && PT <= Z - CHARPOS (tlendpos)
16783
16784
16785
16786
16787
16788
16789 && (NILP (Vdisplay_line_numbers)
16790 || EQ (Vdisplay_line_numbers, Qvisual))
16791
16792
16793 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16794 CHARPOS (tlendpos)))
16795 {
16796 if (CHARPOS (tlbufpos) > BEGV
16797 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16798 && (CHARPOS (tlbufpos) == ZV
16799 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16800
16801 goto cancel;
16802 else if (window_outdated (w) || MINI_WINDOW_P (w))
16803 {
16804
16805
16806
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16817
16818
16819 struct it it;
16820 int line_height_before = this_line_pixel_height;
16821
16822
16823
16824 start_display (&it, w, tlbufpos);
16825
16826
16827 if (it.current_x != this_line_start_x)
16828 goto cancel;
16829
16830
16831
16832
16833 if (it.sp > 1
16834 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16835 goto cancel;
16836 redisplay_trace ("trying display optimization 1\n");
16837 w->cursor.vpos = -1;
16838 overlay_arrow_seen = false;
16839 it.vpos = this_line_vpos;
16840 it.current_y = this_line_y;
16841 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16842 display_line (&it, -1);
16843
16844
16845
16846 if (w->cursor.vpos >= 0
16847
16848
16849 && CHARPOS (this_line_start_pos)
16850
16851 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16852
16853
16854 && this_line_pixel_height == line_height_before
16855
16856
16857
16858
16859 && !hscrolling_current_line_p (w))
16860 {
16861
16862
16863 if (it.current_y < it.last_visible_y)
16864 {
16865 struct glyph_row *row
16866 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16867 ptrdiff_t delta, delta_bytes;
16868
16869
16870
16871
16872
16873
16874 delta = (Z
16875 - CHARPOS (tlendpos)
16876 - MATRIX_ROW_START_CHARPOS (row));
16877 delta_bytes = (Z_BYTE
16878 - BYTEPOS (tlendpos)
16879 - MATRIX_ROW_START_BYTEPOS (row));
16880
16881 increment_matrix_positions (w->current_matrix,
16882 this_line_vpos + 1,
16883 w->current_matrix->nrows,
16884 delta, delta_bytes);
16885 }
16886
16887
16888
16889
16890 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16891 {
16892 if (w->window_end_vpos < this_line_vpos)
16893 w->window_end_vpos = this_line_vpos;
16894 }
16895 else if (w->window_end_vpos == this_line_vpos
16896 && this_line_vpos > 0)
16897 w->window_end_vpos = this_line_vpos - 1;
16898 w->window_end_valid = false;
16899
16900
16901 w->desired_matrix->no_scrolling_p = true;
16902
16903 #ifdef GLYPH_DEBUG
16904 *w->desired_matrix->method = 0;
16905 debug_method_add (w, "optimization 1");
16906 #endif
16907 #ifdef HAVE_WINDOW_SYSTEM
16908 update_window_fringes (w, false);
16909 #endif
16910 goto update;
16911 }
16912 else
16913 goto cancel;
16914 }
16915 else if (
16916 PT == w->last_point
16917
16918
16919
16920
16921 && 0 <= w->cursor.vpos
16922 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
16923 {
16924 if (!must_finish)
16925 {
16926 do_pending_window_change (true);
16927
16928 if (WINDOWP (selected_window)
16929 && (w = XWINDOW (selected_window)) != sw)
16930 goto retry;
16931
16932
16933
16934 if (w->cursor_off_p == w->last_cursor_off_p)
16935 goto end_of_redisplay;
16936 }
16937 goto update;
16938 }
16939
16940
16941 else if (NILP (Vshow_trailing_whitespace)
16942 && !cursor_in_echo_area
16943 && !composition_break_at_point)
16944 {
16945 struct it it;
16946 struct glyph_row *row;
16947
16948
16949
16950
16951 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
16952 NULL, DEFAULT_FACE_ID);
16953 it.current_x = this_line_start_x;
16954 it.current_y = this_line_y;
16955 it.vpos = this_line_vpos;
16956
16957 if (current_buffer->long_line_optimizations_p
16958 && it.line_wrap == TRUNCATE
16959 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16960 {
16961
16962
16963
16964 reseat_at_next_visible_line_start (&it, false);
16965 if (IT_CHARPOS (it) <= PT)
16966 it.vpos = this_line_vpos + 1;
16967 }
16968 else
16969 {
16970
16971
16972 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16973 }
16974
16975 if (it.vpos == this_line_vpos
16976 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
16977 row->enabled_p))
16978 {
16979 eassert (this_line_vpos == it.vpos);
16980 eassert (this_line_y == it.current_y);
16981 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
16982 if (cursor_row_fully_visible_p (w, false, true, false))
16983 {
16984 #ifdef GLYPH_DEBUG
16985 *w->desired_matrix->method = 0;
16986 debug_method_add (w, "optimization 3");
16987 #endif
16988 goto update;
16989 }
16990 else
16991 goto cancel;
16992 }
16993 else
16994 goto cancel;
16995 }
16996
16997 cancel:
16998
16999 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17000 }
17001
17002 CHARPOS (this_line_start_pos) = 0;
17003 ++clear_face_cache_count;
17004 #ifdef HAVE_WINDOW_SYSTEM
17005 ++clear_image_cache_count;
17006 #endif
17007
17008
17009
17010
17011
17012
17013 if (consider_all_windows_p)
17014 {
17015 FOR_EACH_FRAME (tail, frame)
17016 XFRAME (frame)->updated_p = false;
17017
17018 propagate_buffer_redisplay ();
17019
17020 FOR_EACH_FRAME (tail, frame)
17021 {
17022 struct frame *f = XFRAME (frame);
17023
17024
17025
17026 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17027 && !EQ (FRAME_TTY (f)->top_frame, frame))
17028 continue;
17029
17030 retry_frame:
17031 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17032 {
17033 bool gcscrollbars
17034
17035 = f->redisplay || !REDISPLAY_SOME_P ();
17036 bool f_redisplay_flag = f->redisplay;
17037
17038
17039
17040
17041 if (!FRAME_LIVE_P (f))
17042 continue;
17043
17044
17045
17046 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17047 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17048
17049 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17050 {
17051
17052
17053
17054
17055
17056
17057
17058 f->inhibit_clear_image_cache = true;
17059 redisplay_windows (FRAME_ROOT_WINDOW (f));
17060 }
17061
17062
17063 else if (!REDISPLAY_SOME_P ())
17064 f->redisplay = true;
17065
17066
17067 if (!FRAME_LIVE_P (f))
17068 continue;
17069
17070
17071
17072 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17073 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17074
17075 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17076 {
17077
17078 if (f->fonts_changed)
17079 {
17080 adjust_frame_glyphs (f);
17081
17082
17083
17084 SET_FRAME_GARBAGED (f);
17085 f->fonts_changed = false;
17086 goto retry_frame;
17087 }
17088
17089
17090 if (!f->already_hscrolled_p)
17091 {
17092 f->already_hscrolled_p = true;
17093 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17094 && hscroll_windows (f->root_window))
17095 {
17096 hscroll_retries++;
17097 goto retry_frame;
17098 }
17099 }
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112 if (!f_redisplay_flag && f->redisplay)
17113 goto retry_frame;
17114
17115
17116
17117
17118
17119
17120
17121
17122
17123 if (FRAME_GARBAGED_P (f)
17124 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17125 goto retry;
17126
17127 #ifdef HAVE_WINDOW_SYSTEM
17128 if (FRAME_WINDOW_P (f)
17129 && FRAME_RIF (f)->clear_under_internal_border)
17130 FRAME_RIF (f)->clear_under_internal_border (f);
17131 #endif
17132
17133
17134
17135 if (interrupt_input)
17136 unrequest_sigio ();
17137 STOP_POLLING;
17138
17139 pending |= update_frame (f, false, false);
17140
17141
17142
17143
17144
17145
17146
17147 if (FRAME_GARBAGED_P (f))
17148 {
17149 fset_redisplay (f);
17150 f->garbaged = false;
17151 goto retry_frame;
17152 }
17153 f->cursor_type_changed = false;
17154 f->updated_p = true;
17155 f->inhibit_clear_image_cache = false;
17156 }
17157 }
17158 }
17159
17160 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17161
17162 if (!pending)
17163 {
17164
17165
17166
17167 FOR_EACH_FRAME (tail, frame)
17168 {
17169 struct frame *f = XFRAME (frame);
17170 if (f->updated_p)
17171 {
17172 f->redisplay = false;
17173 f->garbaged = false;
17174 mark_window_display_accurate (f->root_window, true);
17175 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17176 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17177 }
17178 }
17179 }
17180 }
17181 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17182 {
17183 sf->inhibit_clear_image_cache = true;
17184 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17185
17186
17187 internal_condition_case_1 (redisplay_window_1, selected_window,
17188 list_of_error,
17189 redisplay_window_error);
17190 if (update_miniwindow_p)
17191 {
17192 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17193
17194 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17195 internal_condition_case_1 (redisplay_window_1, mini_window,
17196 list_of_error,
17197 redisplay_window_error);
17198 }
17199
17200
17201
17202 update:
17203
17204
17205
17206 if (sf->fonts_changed || sf->redisplay)
17207 {
17208 if (sf->redisplay)
17209 {
17210
17211
17212
17213
17214
17215
17216 windows_or_buffers_changed = 50;
17217 }
17218 goto retry;
17219 }
17220
17221
17222
17223 inhibit_free_realized_faces = true;
17224
17225
17226
17227
17228 if (interrupt_input)
17229 unrequest_sigio ();
17230 STOP_POLLING;
17231
17232 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17233 {
17234 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17235 && hscroll_windows (selected_window))
17236 {
17237 hscroll_retries++;
17238 goto retry;
17239 }
17240
17241 XWINDOW (selected_window)->must_be_updated_p = true;
17242 pending = update_frame (sf, false, false);
17243 sf->cursor_type_changed = false;
17244 sf->inhibit_clear_image_cache = false;
17245 }
17246
17247
17248
17249
17250
17251
17252 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17253 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17254
17255 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17256 {
17257 XWINDOW (mini_window)->must_be_updated_p = true;
17258 pending |= update_frame (mini_frame, false, false);
17259 mini_frame->cursor_type_changed = false;
17260 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17261 && hscroll_windows (mini_window))
17262 {
17263 hscroll_retries++;
17264 goto retry;
17265 }
17266 }
17267 }
17268
17269
17270
17271 if (pending)
17272 {
17273
17274
17275
17276 CHARPOS (this_line_start_pos) = 0;
17277
17278
17279 update_overlay_arrows (0);
17280
17281
17282
17283 if (!WINDOW_FULL_WIDTH_P (w)
17284 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17285 update_mode_lines = 36;
17286 }
17287 else
17288 {
17289 if (!consider_all_windows_p)
17290 {
17291
17292
17293 if (XBUFFER (w->contents)->text->redisplay
17294 && buffer_window_count (XBUFFER (w->contents)) > 1)
17295
17296
17297 propagate_buffer_redisplay ();
17298 mark_window_display_accurate_1 (w, true);
17299
17300
17301 update_overlay_arrows (1);
17302
17303 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17304 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17305 }
17306
17307 update_mode_lines = 0;
17308 windows_or_buffers_changed = 0;
17309 }
17310
17311
17312
17313
17314
17315 if (interrupt_input)
17316 request_sigio ();
17317 RESUME_POLLING;
17318
17319
17320
17321
17322
17323
17324
17325 if (!pending)
17326 {
17327 int new_count = 0;
17328
17329 FOR_EACH_FRAME (tail, frame)
17330 {
17331 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17332 new_count++;
17333 }
17334
17335 if (new_count != number_of_visible_frames)
17336 windows_or_buffers_changed = 52;
17337 }
17338
17339
17340 do_pending_window_change (true);
17341
17342
17343
17344 if ((windows_or_buffers_changed && !pending)
17345 || (WINDOWP (selected_window)
17346 && (w = XWINDOW (selected_window)) != sw))
17347 goto retry;
17348
17349
17350
17351
17352
17353
17354
17355 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17356 {
17357 clear_face_cache (false);
17358 clear_face_cache_count = 0;
17359 }
17360
17361 #ifdef HAVE_WINDOW_SYSTEM
17362 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17363 {
17364 clear_image_caches (Qnil);
17365 clear_image_cache_count = 0;
17366 }
17367 #endif
17368
17369 end_of_redisplay:
17370 #ifdef HAVE_NS
17371 ns_set_doc_edited ();
17372 #endif
17373 if (interrupt_input && interrupts_deferred)
17374 request_sigio ();
17375
17376
17377
17378 if (max_redisplay_ticks > 0)
17379 update_redisplay_ticks (0, NULL);
17380
17381 unbind_to (count, Qnil);
17382 RESUME_POLLING;
17383 }
17384
17385 static void
17386 unwind_redisplay_preserve_echo_area (void)
17387 {
17388 unblock_buffer_flips ();
17389 }
17390
17391
17392
17393
17394
17395
17396
17397
17398
17399
17400
17401
17402 void
17403 redisplay_preserve_echo_area (int from_where)
17404 {
17405 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17406
17407 block_input ();
17408 specpdl_ref count = SPECPDL_INDEX ();
17409 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17410 block_buffer_flips ();
17411 unblock_input ();
17412
17413 if (!NILP (echo_area_buffer[1]))
17414 {
17415
17416
17417 display_last_displayed_message_p = true;
17418 redisplay_internal ();
17419 display_last_displayed_message_p = false;
17420 }
17421 else
17422 redisplay_internal ();
17423
17424 flush_frame (SELECTED_FRAME ());
17425 unbind_to (count, Qnil);
17426 }
17427
17428
17429
17430
17431 static void
17432 unwind_redisplay (void)
17433 {
17434 redisplaying_p = false;
17435 unblock_buffer_flips ();
17436 }
17437
17438
17439
17440 void
17441 unwind_display_working_on_window (void)
17442 {
17443 display_working_on_window_p = false;
17444 }
17445
17446
17447
17448
17449
17450
17451 static void
17452 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17453 {
17454 struct buffer *b = XBUFFER (w->contents);
17455
17456 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17457 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17458 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17459
17460 if (accurate_p)
17461 {
17462 b->clip_changed = false;
17463 b->prevent_redisplay_optimizations_p = false;
17464 eassert (buffer_window_count (b) > 0);
17465
17466
17467
17468 b->text->redisplay = false;
17469
17470 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17471 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17472 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17473 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17474
17475 w->current_matrix->buffer = b;
17476 w->current_matrix->begv = BUF_BEGV (b);
17477 w->current_matrix->zv = BUF_ZV (b);
17478 w->current_matrix->header_line_p = window_wants_header_line (w);
17479 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17480
17481 w->last_cursor_vpos = w->cursor.vpos;
17482 w->last_cursor_off_p = w->cursor_off_p;
17483
17484 if (w == XWINDOW (selected_window))
17485 w->last_point = BUF_PT (b);
17486 else
17487 w->last_point = marker_position (w->pointm);
17488
17489 w->window_end_valid = true;
17490 w->update_mode_line = false;
17491 w->preserve_vscroll_p = false;
17492 }
17493
17494 w->redisplay = !accurate_p;
17495 }
17496
17497
17498
17499
17500
17501
17502
17503 void
17504 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17505 {
17506 struct window *w;
17507
17508 for (; !NILP (window); window = w->next)
17509 {
17510 w = XWINDOW (window);
17511 if (WINDOWP (w->contents))
17512 mark_window_display_accurate (w->contents, accurate_p);
17513 else
17514 mark_window_display_accurate_1 (w, accurate_p);
17515 }
17516
17517 if (accurate_p)
17518 update_overlay_arrows (1);
17519 else
17520
17521
17522
17523 update_overlay_arrows (-1);
17524 }
17525
17526
17527
17528
17529
17530
17531
17532 Lisp_Object
17533 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17534 {
17535 Lisp_Object val;
17536
17537 if (ASCII_CHAR_P (c))
17538 {
17539 val = dp->ascii;
17540 if (SUB_CHAR_TABLE_P (val))
17541 val = XSUB_CHAR_TABLE (val)->contents[c];
17542 }
17543 else
17544 {
17545 Lisp_Object table;
17546
17547 XSETCHAR_TABLE (table, dp);
17548 val = char_table_ref (table, c);
17549 }
17550 if (NILP (val))
17551 val = dp->defalt;
17552 return val;
17553 }
17554
17555 static int buffer_flip_blocked_depth;
17556
17557 static void
17558 block_buffer_flips (void)
17559 {
17560 eassert (buffer_flip_blocked_depth >= 0);
17561 buffer_flip_blocked_depth++;
17562 }
17563
17564 static void
17565 unblock_buffer_flips (void)
17566 {
17567 eassert (buffer_flip_blocked_depth > 0);
17568 if (--buffer_flip_blocked_depth == 0)
17569 {
17570 Lisp_Object tail, frame;
17571 block_input ();
17572 FOR_EACH_FRAME (tail, frame)
17573 {
17574 struct frame *f = XFRAME (frame);
17575 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17576 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17577 }
17578 unblock_input ();
17579 }
17580 }
17581
17582 bool
17583 buffer_flipping_blocked_p (void)
17584 {
17585 return buffer_flip_blocked_depth > 0;
17586 }
17587
17588
17589
17590
17591
17592
17593
17594
17595 static void
17596 redisplay_windows (Lisp_Object window)
17597 {
17598 while (!NILP (window))
17599 {
17600 struct window *w = XWINDOW (window);
17601
17602 if (WINDOWP (w->contents))
17603 redisplay_windows (w->contents);
17604 else if (BUFFERP (w->contents))
17605 {
17606 displayed_buffer = XBUFFER (w->contents);
17607
17608
17609 internal_condition_case_1 (redisplay_window_0, window,
17610 list_of_error,
17611 redisplay_window_error);
17612 }
17613
17614 window = w->next;
17615 }
17616 }
17617
17618 static Lisp_Object
17619 redisplay_window_error (Lisp_Object error_data)
17620 {
17621 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17622
17623
17624
17625 if (max_redisplay_ticks > 0
17626 && CONSP (error_data)
17627 && EQ (XCAR (error_data), Qerror)
17628 && STRINGP (XCAR (XCDR (error_data))))
17629 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17630 XCAR (XCDR (error_data))),
17631 Vdelayed_warnings_list);
17632 return Qnil;
17633 }
17634
17635 static Lisp_Object
17636 redisplay_window_0 (Lisp_Object window)
17637 {
17638 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17639 redisplay_window (window, false);
17640 return Qnil;
17641 }
17642
17643 static Lisp_Object
17644 redisplay_window_1 (Lisp_Object window)
17645 {
17646 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17647 redisplay_window (window, true);
17648 return Qnil;
17649 }
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
17664
17665
17666
17667
17668
17669 void
17670 update_redisplay_ticks (int ticks, struct window *w)
17671 {
17672
17673 static struct window *cwindow;
17674 static EMACS_INT window_ticks;
17675
17676
17677
17678
17679 if (!ticks && w != cwindow)
17680 {
17681 cwindow = w;
17682 window_ticks = 0;
17683 }
17684
17685
17686 if ((!w && !redisplaying_p && !display_working_on_window_p)
17687
17688
17689 || (w && MINI_WINDOW_P (w)))
17690 return;
17691
17692 if (ticks > 0)
17693 window_ticks += ticks;
17694 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17695 {
17696
17697
17698
17699 Lisp_Object contents = w ? w->contents : Qnil;
17700 char *bufname =
17701 NILP (contents)
17702 ? SSDATA (BVAR (current_buffer, name))
17703 : (BUFFERP (contents)
17704 ? SSDATA (BVAR (XBUFFER (contents), name))
17705 : (char *) "<unknown>");
17706
17707 windows_or_buffers_changed = 177;
17708
17709
17710
17711 if (w && w->desired_matrix)
17712 w->desired_matrix->no_scrolling_p = true;
17713 error ("Window showing buffer %s takes too long to redisplay", bufname);
17714 }
17715 }
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726 static bool
17727 set_cursor_from_row (struct window *w, struct glyph_row *row,
17728 struct glyph_matrix *matrix,
17729 ptrdiff_t delta, ptrdiff_t delta_bytes,
17730 int dy, int dvpos)
17731 {
17732 struct glyph *glyph = row->glyphs[TEXT_AREA];
17733 struct glyph *end = glyph + row->used[TEXT_AREA];
17734 struct glyph *cursor = NULL;
17735
17736 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17737 int x = row->x;
17738 ptrdiff_t pt_old = PT - delta;
17739 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17740 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17741 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17742
17743
17744 struct glyph *glyphs_end = end;
17745
17746
17747 bool match_with_avoid_cursor = false;
17748
17749
17750 bool string_seen = false;
17751
17752
17753 ptrdiff_t bpos_max = pos_before;
17754 ptrdiff_t bpos_min = pos_after;
17755
17756
17757 ptrdiff_t bpos_covered = 0;
17758
17759
17760 bool string_from_text_prop = false;
17761
17762
17763
17764
17765 eassert (!row->mode_line_p);
17766 if (row->mode_line_p)
17767 return false;
17768
17769
17770
17771
17772 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17773 {
17774 if (!row->reversed_p)
17775 {
17776 while (glyph < end
17777 && NILP (glyph->object)
17778 && glyph->charpos < 0)
17779 {
17780 x += glyph->pixel_width;
17781 ++glyph;
17782 }
17783 while (end > glyph
17784 && NILP ((end - 1)->object)
17785
17786
17787 && (end - 1)->charpos <= 0)
17788 --end;
17789 glyph_before = glyph - 1;
17790 glyph_after = end;
17791 }
17792 else
17793 {
17794 struct glyph *g;
17795
17796
17797
17798 glyphs_end = end = glyph - 1;
17799 glyph += row->used[TEXT_AREA] - 1;
17800
17801 while (glyph > end + 1
17802 && NILP (glyph->object)
17803 && glyph->charpos < 0)
17804 --glyph;
17805 if (NILP (glyph->object) && glyph->charpos < 0)
17806 --glyph;
17807
17808
17809 for (x = 0, g = end + 1; g < glyph; g++)
17810 x += g->pixel_width;
17811 while (end < glyph
17812 && NILP ((end + 1)->object)
17813 && (end + 1)->charpos <= 0)
17814 ++end;
17815 glyph_before = glyph + 1;
17816 glyph_after = end;
17817 }
17818 }
17819 else if (row->reversed_p)
17820 {
17821
17822
17823
17824 cursor = end - 1;
17825
17826
17827
17828 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17829 && !WINDOW_RIGHTMOST_P (w)
17830 && cursor == row->glyphs[LAST_AREA] - 1)
17831 cursor--;
17832 x = -1;
17833 }
17834
17835
17836
17837
17838
17839 if (!row->reversed_p)
17840 while (
17841 glyph < end
17842
17843 && !NILP (glyph->object))
17844 {
17845 if (BUFFERP (glyph->object))
17846 {
17847 ptrdiff_t dpos = glyph->charpos - pt_old;
17848
17849 if (glyph->charpos > bpos_max)
17850 bpos_max = glyph->charpos;
17851 if (glyph->charpos < bpos_min)
17852 bpos_min = glyph->charpos;
17853 if (!glyph->avoid_cursor_p)
17854 {
17855
17856
17857 if (dpos == 0)
17858 {
17859 match_with_avoid_cursor = false;
17860 break;
17861 }
17862
17863
17864 if (0 > dpos && dpos > pos_before - pt_old)
17865 {
17866 pos_before = glyph->charpos;
17867 glyph_before = glyph;
17868 }
17869 else if (0 < dpos && dpos < pos_after - pt_old)
17870 {
17871 pos_after = glyph->charpos;
17872 glyph_after = glyph;
17873 }
17874 }
17875 else if (dpos == 0)
17876 match_with_avoid_cursor = true;
17877 }
17878 else if (STRINGP (glyph->object))
17879 {
17880 Lisp_Object chprop;
17881 ptrdiff_t glyph_pos = glyph->charpos;
17882
17883 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17884 glyph->object);
17885 if (!NILP (chprop))
17886 {
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897 ptrdiff_t prop_pos =
17898 string_buffer_position_lim (glyph->object, pos_before,
17899 pos_after, false);
17900
17901 if (prop_pos >= pos_before)
17902 bpos_max = prop_pos;
17903 }
17904 if (FIXNUMP (chprop))
17905 {
17906 bpos_covered = bpos_max + XFIXNUM (chprop);
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17919 {
17920 cursor = glyph;
17921 break;
17922 }
17923 }
17924
17925 string_seen = true;
17926 }
17927 x += glyph->pixel_width;
17928 ++glyph;
17929 }
17930 else if (glyph > end)
17931 while (!NILP (glyph->object))
17932 {
17933 if (BUFFERP (glyph->object))
17934 {
17935 ptrdiff_t dpos = glyph->charpos - pt_old;
17936
17937 if (glyph->charpos > bpos_max)
17938 bpos_max = glyph->charpos;
17939 if (glyph->charpos < bpos_min)
17940 bpos_min = glyph->charpos;
17941 if (!glyph->avoid_cursor_p)
17942 {
17943 if (dpos == 0)
17944 {
17945 match_with_avoid_cursor = false;
17946 break;
17947 }
17948 if (0 > dpos && dpos > pos_before - pt_old)
17949 {
17950 pos_before = glyph->charpos;
17951 glyph_before = glyph;
17952 }
17953 else if (0 < dpos && dpos < pos_after - pt_old)
17954 {
17955 pos_after = glyph->charpos;
17956 glyph_after = glyph;
17957 }
17958 }
17959 else if (dpos == 0)
17960 match_with_avoid_cursor = true;
17961 }
17962 else if (STRINGP (glyph->object))
17963 {
17964 Lisp_Object chprop;
17965 ptrdiff_t glyph_pos = glyph->charpos;
17966
17967 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17968 glyph->object);
17969 if (!NILP (chprop))
17970 {
17971 ptrdiff_t prop_pos =
17972 string_buffer_position_lim (glyph->object, pos_before,
17973 pos_after, false);
17974
17975 if (prop_pos >= pos_before)
17976 bpos_max = prop_pos;
17977 }
17978 if (FIXNUMP (chprop))
17979 {
17980 bpos_covered = bpos_max + XFIXNUM (chprop);
17981
17982
17983
17984 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17985 {
17986 cursor = glyph;
17987 break;
17988 }
17989 }
17990 string_seen = true;
17991 }
17992 --glyph;
17993 if (glyph == glyphs_end)
17994 {
17995 x--;
17996 break;
17997 }
17998 x -= glyph->pixel_width;
17999 }
18000
18001
18002
18003
18004 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18005 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18006 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18007 {
18008
18009
18010
18011
18012
18013 bool empty_line_p =
18014 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18015 && NILP (glyph->object) && glyph->charpos > 0
18016
18017
18018
18019
18020 && !(row->continued_p || row->truncated_on_right_p));
18021
18022 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18023 {
18024 ptrdiff_t ellipsis_pos;
18025
18026
18027 if (!row->reversed_p)
18028 {
18029 ellipsis_pos = (glyph - 1)->charpos;
18030 while (glyph > row->glyphs[TEXT_AREA]
18031 && (glyph - 1)->charpos == ellipsis_pos)
18032 glyph--, x -= glyph->pixel_width;
18033
18034
18035
18036 x += glyph->pixel_width;
18037 glyph++;
18038 }
18039 else
18040 {
18041 ellipsis_pos = (glyph + 1)->charpos;
18042 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18043 && (glyph + 1)->charpos == ellipsis_pos)
18044 glyph++, x += glyph->pixel_width;
18045 x -= glyph->pixel_width;
18046 glyph--;
18047 }
18048 }
18049 else if (match_with_avoid_cursor)
18050 {
18051 cursor = glyph_after;
18052 x = -1;
18053 }
18054 else if (string_seen)
18055 {
18056 int incr = row->reversed_p ? -1 : +1;
18057
18058
18059
18060
18061
18062
18063 struct glyph *start, *stop;
18064 ptrdiff_t pos = pos_before;
18065
18066 x = -1;
18067
18068
18069
18070
18071
18072
18073 if (row->ends_in_newline_from_string_p)
18074 {
18075 glyph_after = end;
18076 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18077 }
18078
18079
18080
18081
18082
18083
18084
18085
18086
18087 if (!row->reversed_p)
18088 {
18089 start = min (glyph_before, glyph_after);
18090 stop = max (glyph_before, glyph_after);
18091 }
18092 else
18093 {
18094 start = max (glyph_before, glyph_after);
18095 stop = min (glyph_before, glyph_after);
18096 }
18097 for (glyph = start + incr;
18098 row->reversed_p ? glyph > stop : glyph < stop; )
18099 {
18100
18101
18102
18103
18104 if (STRINGP (glyph->object))
18105 {
18106 Lisp_Object str;
18107 ptrdiff_t tem;
18108
18109
18110 ptrdiff_t lim = pos_after
18111 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18112
18113 string_from_text_prop = false;
18114 str = glyph->object;
18115 tem = string_buffer_position_lim (str, pos, lim, false);
18116 if (tem == 0
18117 || pos <= tem)
18118 {
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129 if (tem == 0
18130 || tem == pt_old
18131 || (tem - pt_old > 0 && tem < pos_after))
18132 {
18133
18134
18135
18136
18137
18138
18139 ptrdiff_t strpos = glyph->charpos;
18140
18141 if (tem)
18142 {
18143 cursor = glyph;
18144 string_from_text_prop = true;
18145 }
18146 for ( ;
18147 (row->reversed_p ? glyph > stop : glyph < stop)
18148 && EQ (glyph->object, str);
18149 glyph += incr)
18150 {
18151 Lisp_Object cprop;
18152 ptrdiff_t gpos = glyph->charpos;
18153
18154 cprop = Fget_char_property (make_fixnum (gpos),
18155 Qcursor,
18156 glyph->object);
18157 if (!NILP (cprop))
18158 {
18159 cursor = glyph;
18160 break;
18161 }
18162 if (tem && glyph->charpos < strpos)
18163 {
18164 strpos = glyph->charpos;
18165 cursor = glyph;
18166 }
18167 }
18168
18169 if (tem == pt_old
18170 || (tem - pt_old > 0 && tem < pos_after))
18171 goto compute_x;
18172 }
18173 if (tem)
18174 pos = tem + 1;
18175 }
18176
18177
18178 while ((row->reversed_p ? glyph > stop : glyph < stop)
18179 && EQ (glyph->object, str))
18180 glyph += incr;
18181 }
18182 else
18183 glyph += incr;
18184 }
18185
18186
18187
18188 if (cursor == NULL
18189 && (row->reversed_p ? glyph <= end : glyph >= end)
18190 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18191 && STRINGP (end->object)
18192 && row->continued_p)
18193 return false;
18194 }
18195
18196
18197
18198
18199
18200 else if (row->truncated_on_left_p && pt_old < bpos_min)
18201 {
18202 cursor = glyph_before;
18203 x = -1;
18204 }
18205 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18206
18207 || (!empty_line_p
18208 && (row->reversed_p
18209 ? glyph_after > glyphs_end
18210 : glyph_after < glyphs_end)))
18211 {
18212 cursor = glyph_after;
18213 x = -1;
18214 }
18215 }
18216
18217 compute_x:
18218 if (cursor != NULL)
18219 glyph = cursor;
18220 else if (glyph == glyphs_end
18221 && pos_before == pos_after
18222 && STRINGP ((row->reversed_p
18223 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18224 : row->glyphs[TEXT_AREA])->object))
18225 {
18226
18227
18228
18229
18230 glyph =
18231 row->reversed_p
18232 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18233 : row->glyphs[TEXT_AREA];
18234 }
18235 if (x < 0)
18236 {
18237 struct glyph *g;
18238
18239
18240 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18241 {
18242 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18243 emacs_abort ();
18244 x += g->pixel_width;
18245 }
18246 }
18247
18248
18249
18250
18251
18252
18253 if (
18254 w->cursor.vpos >= 0
18255
18256 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18257
18258
18259
18260
18261
18262 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18263 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18264 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18265 {
18266 struct glyph *g1
18267 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18268
18269
18270 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18271 return false;
18272
18273
18274 if (
18275 w->cursor.hpos >= 0
18276 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18277 && ((BUFFERP (g1->object)
18278 && (g1->charpos == pt_old
18279 || (BUFFERP (glyph->object)
18280 && eabs (g1->charpos - pt_old)
18281 < eabs (glyph->charpos - pt_old))))
18282
18283
18284 || (STRINGP (g1->object)
18285 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18286 Qcursor, g1->object))
18287
18288
18289
18290 || (EQ (g1->object, glyph->object)
18291 && string_from_text_prop)
18292
18293
18294 || (NILP (glyph->object)
18295 && glyph->charpos != pt_old)))))
18296 return false;
18297
18298 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18299
18300
18301
18302 || (!row->continued_p
18303 && NILP (glyph->object)
18304 && glyph->charpos == 0
18305 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18306
18307
18308
18309
18310
18311 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18312 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18313 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18314 return false;
18315 }
18316 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18317 w->cursor.x = x;
18318 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18319 w->cursor.y = row->y + dy;
18320
18321 if (w == XWINDOW (selected_window))
18322 {
18323 if (!row->continued_p
18324 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18325 && row->x == 0)
18326 {
18327 this_line_buffer = XBUFFER (w->contents);
18328
18329 CHARPOS (this_line_start_pos)
18330 = MATRIX_ROW_START_CHARPOS (row) + delta;
18331 BYTEPOS (this_line_start_pos)
18332 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18333
18334 CHARPOS (this_line_end_pos)
18335 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18336 BYTEPOS (this_line_end_pos)
18337 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18338
18339 this_line_y = w->cursor.y;
18340 this_line_pixel_height = row->height;
18341 this_line_vpos = w->cursor.vpos;
18342 this_line_start_x = row->x;
18343 }
18344 else
18345 CHARPOS (this_line_start_pos) = 0;
18346 }
18347
18348 return true;
18349 }
18350
18351
18352
18353
18354
18355
18356
18357 static struct text_pos
18358 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18359 {
18360 struct window *w = XWINDOW (window);
18361 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18362
18363 eassert (current_buffer == XBUFFER (w->contents));
18364
18365 if (!NILP (Vwindow_scroll_functions))
18366 {
18367 specpdl_ref count = SPECPDL_INDEX ();
18368 specbind (Qinhibit_quit, Qt);
18369 safe_run_hooks_2
18370 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18371 unbind_to (count, Qnil);
18372 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18373
18374 set_buffer_internal (XBUFFER (w->contents));
18375 }
18376
18377 return startp;
18378 }
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393
18394
18395
18396
18397
18398
18399
18400
18401 static bool
18402 cursor_row_fully_visible_p (struct window *w, bool force_p,
18403 bool current_matrix_p,
18404 bool just_test_user_preference_p)
18405 {
18406 struct glyph_matrix *matrix;
18407 struct glyph_row *row;
18408 int window_height;
18409 Lisp_Object mclfv_p =
18410 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18411
18412
18413 if (BASE_EQ (mclfv_p, Qunbound))
18414 mclfv_p = Vmake_cursor_line_fully_visible;
18415
18416
18417 if (FUNCTIONP (mclfv_p))
18418 {
18419 Lisp_Object window;
18420 XSETWINDOW (window, w);
18421
18422
18423 Lisp_Object val = safe_call1 (mclfv_p, window);
18424 if (NILP (val))
18425 return true;
18426 else if (just_test_user_preference_p)
18427 return false;
18428 }
18429 else if (NILP (mclfv_p))
18430 return true;
18431 else if (just_test_user_preference_p)
18432 return false;
18433
18434
18435
18436 if (w->cursor.vpos < 0)
18437 return true;
18438
18439 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18440 row = MATRIX_ROW (matrix, w->cursor.vpos);
18441
18442
18443 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18444 return true;
18445
18446
18447
18448 window_height = window_box_height (w);
18449 if (row->height >= window_height)
18450 {
18451 if (!force_p || MINI_WINDOW_P (w)
18452 || w->vscroll || w->cursor.vpos == 0)
18453 return true;
18454 }
18455 return false;
18456 }
18457
18458
18459
18460
18461
18462
18463
18464
18465
18466
18467
18468
18469
18470
18471
18472
18473
18474
18475
18476
18477 enum
18478 {
18479 SCROLLING_SUCCESS = 1,
18480 SCROLLING_FAILED = 0,
18481 SCROLLING_NEED_LARGER_MATRICES = -1
18482 };
18483
18484
18485
18486
18487
18488 #define SCROLL_LIMIT 100
18489
18490 static int
18491 try_scrolling (Lisp_Object window, bool just_this_one_p,
18492 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18493 bool temp_scroll_step, bool last_line_misfit)
18494 {
18495 struct window *w = XWINDOW (window);
18496 struct text_pos pos, startp;
18497 struct it it;
18498 int this_scroll_margin, scroll_max, rc, height;
18499 int dy = 0, amount_to_scroll = 0;
18500 bool scroll_down_p = false;
18501 int extra_scroll_margin_lines = last_line_misfit;
18502 Lisp_Object aggressive;
18503
18504 int scroll_limit = SCROLL_LIMIT;
18505 int frame_line_height = default_line_pixel_height (w);
18506
18507 #ifdef GLYPH_DEBUG
18508 debug_method_add (w, "try_scrolling");
18509 #endif
18510
18511 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18512
18513 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18514
18515
18516
18517
18518
18519 if (arg_scroll_conservatively > scroll_limit)
18520 {
18521 arg_scroll_conservatively = scroll_limit + 1;
18522 scroll_max = scroll_limit * frame_line_height;
18523 }
18524 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18525
18526
18527 {
18528 intmax_t scroll_lines_max
18529 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18530 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18531 scroll_max = scroll_lines * frame_line_height;
18532 }
18533 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18534 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18535
18536
18537 scroll_max = 10 * frame_line_height;
18538 else
18539 scroll_max = 0;
18540
18541 too_near_end:
18542
18543
18544 if (PT > CHARPOS (startp))
18545 {
18546 int scroll_margin_y;
18547
18548
18549
18550 start_display (&it, w, startp);
18551 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18552 - this_scroll_margin
18553 - frame_line_height * extra_scroll_margin_lines;
18554 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18555 (MOVE_TO_POS | MOVE_TO_Y));
18556
18557 if (PT > CHARPOS (it.current.pos))
18558 {
18559 int y0 = line_bottom_y (&it);
18560
18561
18562
18563
18564
18565 int slack = max (scroll_max, 10 * frame_line_height);
18566 int y_to_move = it.last_visible_y + slack;
18567
18568
18569
18570
18571
18572 move_it_to (&it, PT, -1, y_to_move,
18573 -1, MOVE_TO_POS | MOVE_TO_Y);
18574 dy = line_bottom_y (&it) - y0;
18575
18576 if (dy > scroll_max)
18577 return SCROLLING_FAILED;
18578
18579 if (dy > 0)
18580 scroll_down_p = true;
18581 }
18582 else if (PT == IT_CHARPOS (it)
18583 && IT_CHARPOS (it) < ZV
18584 && it.method == GET_FROM_STRING
18585 && arg_scroll_conservatively > scroll_limit
18586 && it.current_x == 0)
18587 {
18588 enum move_it_result skip;
18589 int y1 = it.current_y;
18590 int vpos;
18591
18592
18593
18594
18595
18596
18597
18598 do {
18599 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18600 if (skip != MOVE_NEWLINE_OR_CR
18601 || IT_CHARPOS (it) != PT
18602 || it.method == GET_FROM_BUFFER)
18603 break;
18604 vpos = it.vpos;
18605 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18606 } while (it.vpos > vpos);
18607
18608 dy = it.current_y - y1;
18609
18610 if (dy > scroll_max)
18611 return SCROLLING_FAILED;
18612
18613 if (dy > 0)
18614 scroll_down_p = true;
18615 }
18616 }
18617
18618 if (scroll_down_p)
18619 {
18620
18621
18622
18623
18624 if (arg_scroll_conservatively)
18625 amount_to_scroll
18626 = min (max (dy, frame_line_height),
18627 frame_line_height * arg_scroll_conservatively);
18628 else if (scroll_step || temp_scroll_step)
18629 amount_to_scroll = scroll_max;
18630 else
18631 {
18632 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18633 height = WINDOW_BOX_TEXT_HEIGHT (w);
18634 if (NUMBERP (aggressive))
18635 {
18636 double float_amount = XFLOATINT (aggressive) * height;
18637 int aggressive_scroll = float_amount;
18638 if (aggressive_scroll == 0 && float_amount > 0)
18639 aggressive_scroll = 1;
18640
18641
18642
18643
18644
18645
18646 if (aggressive_scroll + 2 * this_scroll_margin > height)
18647 aggressive_scroll = height - 2 * this_scroll_margin;
18648 amount_to_scroll = dy + aggressive_scroll;
18649 }
18650 }
18651
18652 if (amount_to_scroll <= 0)
18653 return SCROLLING_FAILED;
18654
18655 start_display (&it, w, startp);
18656 if (arg_scroll_conservatively <= scroll_limit)
18657 move_it_vertically (&it, amount_to_scroll);
18658 else
18659 {
18660
18661
18662
18663
18664
18665
18666 struct it it1;
18667 void *it1data = NULL;
18668
18669
18670 int start_y;
18671
18672 SAVE_IT (it1, it, it1data);
18673 start_y = line_bottom_y (&it1);
18674 do {
18675 RESTORE_IT (&it, &it, it1data);
18676 move_it_by_lines (&it, 1);
18677 SAVE_IT (it1, it, it1data);
18678 } while (IT_CHARPOS (it) < ZV
18679 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18680 bidi_unshelve_cache (it1data, true);
18681 }
18682
18683
18684 if (IT_CHARPOS (it) == CHARPOS (startp))
18685 move_it_by_lines (&it, 1);
18686 startp = it.current.pos;
18687 }
18688 else
18689 {
18690 struct text_pos scroll_margin_pos = startp;
18691 int y_offset = 0;
18692
18693
18694
18695 if (this_scroll_margin)
18696 {
18697 int y_start;
18698
18699 start_display (&it, w, startp);
18700 y_start = it.current_y;
18701 move_it_vertically (&it, this_scroll_margin);
18702 scroll_margin_pos = it.current.pos;
18703
18704
18705
18706 if (IT_CHARPOS (it) == ZV
18707 && it.current_y - y_start < this_scroll_margin)
18708 y_offset = this_scroll_margin - (it.current_y - y_start);
18709 }
18710
18711 if (PT < CHARPOS (scroll_margin_pos))
18712 {
18713
18714
18715 int y0, y_to_move;
18716
18717
18718
18719
18720
18721
18722 SET_TEXT_POS (pos, PT, PT_BYTE);
18723 start_display (&it, w, pos);
18724 y0 = it.current_y;
18725 y_to_move = max (it.last_visible_y,
18726 max (scroll_max, 10 * frame_line_height));
18727 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18728 y_to_move, -1,
18729 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18730 dy = it.current_y - y0;
18731 if (dy > scroll_max
18732 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18733 return SCROLLING_FAILED;
18734
18735
18736 dy += y_offset;
18737
18738
18739 start_display (&it, w, startp);
18740
18741 if (arg_scroll_conservatively)
18742 amount_to_scroll
18743 = min (max (dy, frame_line_height),
18744 frame_line_height * arg_scroll_conservatively);
18745 else if (scroll_step || temp_scroll_step)
18746 amount_to_scroll = scroll_max;
18747 else
18748 {
18749 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18750 height = WINDOW_BOX_TEXT_HEIGHT (w);
18751 if (NUMBERP (aggressive))
18752 {
18753 double float_amount = XFLOATINT (aggressive) * height;
18754 int aggressive_scroll = float_amount;
18755 if (aggressive_scroll == 0 && float_amount > 0)
18756 aggressive_scroll = 1;
18757
18758
18759
18760
18761 if (aggressive_scroll + 2 * this_scroll_margin > height)
18762 aggressive_scroll = height - 2 * this_scroll_margin;
18763 amount_to_scroll = dy + aggressive_scroll;
18764 }
18765 }
18766
18767 if (amount_to_scroll <= 0)
18768 return SCROLLING_FAILED;
18769
18770 move_it_vertically_backward (&it, amount_to_scroll);
18771 startp = it.current.pos;
18772 }
18773 }
18774
18775
18776 startp = run_window_scroll_functions (window, startp);
18777
18778
18779
18780 if (!try_window (window, startp, 0))
18781 rc = SCROLLING_NEED_LARGER_MATRICES;
18782 else if (w->cursor.vpos < 0)
18783 {
18784 clear_glyph_matrix (w->desired_matrix);
18785 rc = SCROLLING_FAILED;
18786 }
18787 else
18788 {
18789
18790 if (!just_this_one_p
18791 || current_buffer->clip_changed
18792 || BEG_UNCHANGED < CHARPOS (startp))
18793 w->base_line_number = 0;
18794
18795
18796
18797 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18798 false, false)
18799
18800
18801
18802 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18803 {
18804 clear_glyph_matrix (w->desired_matrix);
18805 ++extra_scroll_margin_lines;
18806 goto too_near_end;
18807 }
18808 rc = SCROLLING_SUCCESS;
18809 }
18810
18811 return rc;
18812 }
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825 static bool
18826 compute_window_start_on_continuation_line (struct window *w)
18827 {
18828 struct text_pos pos, start_pos, pos_before_pt;
18829 bool window_start_changed_p = false;
18830
18831 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18832
18833
18834
18835
18836 if (CHARPOS (start_pos) > BEGV
18837 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18838 {
18839 struct it it;
18840 struct glyph_row *row;
18841
18842
18843 if (CHARPOS (start_pos) < BEGV)
18844 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18845 else if (CHARPOS (start_pos) > ZV)
18846 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18847
18848
18849
18850 row = w->desired_matrix->rows + window_wants_tab_line (w)
18851 + window_wants_header_line (w);
18852 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18853 row, DEFAULT_FACE_ID);
18854 reseat_at_previous_visible_line_start (&it);
18855
18856
18857
18858
18859
18860
18861
18862 if (IT_CHARPOS (it) <= PT
18863 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18864
18865 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18866 {
18867 int min_distance, distance;
18868
18869
18870
18871
18872
18873
18874
18875 pos_before_pt = pos = it.current.pos;
18876 min_distance = DISP_INFINITY;
18877 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18878 distance < min_distance)
18879 {
18880 min_distance = distance;
18881 if (CHARPOS (pos) <= PT)
18882 pos_before_pt = pos;
18883 pos = it.current.pos;
18884 if (it.line_wrap == WORD_WRAP)
18885 {
18886
18887
18888
18889
18890
18891
18892
18893
18894
18895 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
18896 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18897 move_it_to (&it, ZV, 0,
18898 it.current_y + it.max_ascent + it.max_descent, -1,
18899 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18900 }
18901 else
18902 move_it_by_lines (&it, 1);
18903 }
18904
18905
18906
18907
18908
18909 if (CHARPOS (pos) > PT)
18910 pos = pos_before_pt;
18911
18912
18913 SET_MARKER_FROM_TEXT_POS (w->start, pos);
18914 window_start_changed_p = true;
18915 }
18916 }
18917
18918 return window_start_changed_p;
18919 }
18920
18921
18922
18923
18924
18925
18926
18927
18928
18929
18930
18931
18932
18933
18934
18935
18936
18937 enum
18938 {
18939 CURSOR_MOVEMENT_SUCCESS,
18940 CURSOR_MOVEMENT_CANNOT_BE_USED,
18941 CURSOR_MOVEMENT_MUST_SCROLL,
18942 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
18943 };
18944
18945 static int
18946 try_cursor_movement (Lisp_Object window, struct text_pos startp,
18947 bool *scroll_step)
18948 {
18949 struct window *w = XWINDOW (window);
18950 struct frame *f = XFRAME (w->frame);
18951 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
18952
18953 #ifdef GLYPH_DEBUG
18954 if (inhibit_try_cursor_movement)
18955 return rc;
18956 #endif
18957
18958
18959
18960
18961 eassert (w->last_point > 0);
18962
18963
18964
18965 eassert (!w->window_end_valid
18966 || w->window_end_vpos < w->current_matrix->nrows);
18967
18968
18969
18970 if (
18971 PT >= CHARPOS (startp)
18972
18973 && !current_buffer->clip_changed
18974
18975
18976
18977
18978 && !update_mode_lines
18979 && !windows_or_buffers_changed
18980 && !f->cursor_type_changed
18981 && NILP (Vshow_trailing_whitespace)
18982
18983
18984 && !EQ (Vdisplay_line_numbers, Qrelative)
18985 && !EQ (Vdisplay_line_numbers, Qvisual)
18986
18987
18988
18989 && !(!NILP (Vdisplay_line_numbers)
18990 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18991 Qline_number_current_line,
18992 w->frame)))
18993
18994
18995
18996
18997
18998
18999 && !EQ (window, minibuf_window)
19000
19001
19002
19003 && !overlay_arrow_in_current_buffer_p ())
19004 {
19005 int this_scroll_margin, top_scroll_margin;
19006 struct glyph_row *row = NULL;
19007
19008 #ifdef GLYPH_DEBUG
19009 debug_method_add (w, "cursor movement");
19010 #endif
19011
19012 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19013
19014 top_scroll_margin = this_scroll_margin;
19015 if (window_wants_tab_line (w))
19016 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19017 if (window_wants_header_line (w))
19018 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19019
19020
19021
19022 if (w->last_cursor_vpos < 0
19023 || w->last_cursor_vpos >= w->current_matrix->nrows)
19024 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19025 else
19026 {
19027 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19028
19029 if (row->tab_line_p)
19030 ++row;
19031 if (row->mode_line_p)
19032 ++row;
19033 if (!row->enabled_p)
19034 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19035 }
19036
19037 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19038 {
19039 bool scroll_p = false, must_scroll = false;
19040 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19041
19042 if (PT > w->last_point)
19043 {
19044
19045 while (MATRIX_ROW_END_CHARPOS (row) < PT
19046 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19047 {
19048 eassert (row->enabled_p);
19049 ++row;
19050 }
19051
19052
19053
19054
19055 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19056 && MATRIX_ROW_END_CHARPOS (row) == PT
19057 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19058 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19059 && !cursor_row_p (row))
19060 ++row;
19061
19062
19063
19064
19065
19066 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19067 || PT > MATRIX_ROW_END_CHARPOS (row)
19068
19069
19070 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19071 && PT == MATRIX_ROW_END_CHARPOS (row)
19072 && !row->ends_at_zv_p
19073 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19074 scroll_p = true;
19075 }
19076 else if (PT < w->last_point)
19077 {
19078
19079
19080 struct glyph_row *row0 = row;
19081
19082 while (!row->mode_line_p
19083 && (MATRIX_ROW_START_CHARPOS (row) > PT
19084 || (MATRIX_ROW_START_CHARPOS (row) == PT
19085 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19086 || (
19087 row > w->current_matrix->rows
19088 && (row-1)->ends_in_newline_from_string_p))))
19089 && (row->y > top_scroll_margin
19090 || CHARPOS (startp) == BEGV))
19091 {
19092 eassert (row->enabled_p);
19093 --row;
19094 }
19095
19096
19097
19098
19099
19100 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19101 && PT <= MATRIX_ROW_END_CHARPOS (row))
19102 && row0->continued_p)
19103 {
19104 row = row0;
19105 while (MATRIX_ROW_START_CHARPOS (row) > PT
19106 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19107 {
19108 eassert (row->enabled_p);
19109 ++row;
19110 }
19111 }
19112
19113
19114
19115
19116
19117
19118 if (row < w->current_matrix->rows
19119 || row->mode_line_p)
19120 {
19121 row = w->current_matrix->rows;
19122
19123 if (row->tab_line_p)
19124 ++row;
19125 if (row->mode_line_p)
19126 ++row;
19127 }
19128
19129
19130
19131 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19132 && MATRIX_ROW_END_CHARPOS (row) == PT
19133 && !cursor_row_p (row))
19134 ++row;
19135
19136
19137
19138 if ((row->y < top_scroll_margin
19139 && CHARPOS (startp) != BEGV)
19140 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19141 || PT > MATRIX_ROW_END_CHARPOS (row)
19142 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19143 && PT == MATRIX_ROW_END_CHARPOS (row)
19144 && !row->ends_at_zv_p
19145 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19146 scroll_p = true;
19147 }
19148 else
19149 {
19150
19151
19152 rc = CURSOR_MOVEMENT_SUCCESS;
19153 }
19154
19155 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19156 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19157
19158
19159 || (MATRIX_ROW_END_CHARPOS (row-1)
19160 == MATRIX_ROW_START_CHARPOS (row))))
19161 || PT > MATRIX_ROW_END_CHARPOS (row))
19162 {
19163
19164 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19165 must_scroll = true;
19166 }
19167 else if (rc != CURSOR_MOVEMENT_SUCCESS
19168 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19169 {
19170 struct glyph_row *row1;
19171
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19183 MATRIX_ROW_CONTINUATION_LINE_P (row);
19184 --row)
19185 {
19186
19187
19188
19189 if (row <= row1)
19190 {
19191 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19192 break;
19193 }
19194 eassert (row->enabled_p);
19195 }
19196 }
19197 if (must_scroll)
19198 ;
19199 else if (rc != CURSOR_MOVEMENT_SUCCESS
19200 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19201
19202
19203
19204 && !row->mode_line_p
19205 && !cursor_row_fully_visible_p (w, true, true, true))
19206 {
19207 if (PT == MATRIX_ROW_END_CHARPOS (row)
19208 && !row->ends_at_zv_p
19209 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19210 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19211 else if (row->height > window_box_height (w))
19212 {
19213
19214
19215
19216
19217 *scroll_step = true;
19218 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19219 }
19220 else
19221 {
19222 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19223 if (!cursor_row_fully_visible_p (w, false, true, false))
19224 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19225 else
19226 rc = CURSOR_MOVEMENT_SUCCESS;
19227 }
19228 }
19229 else if (scroll_p)
19230 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19231 else if (rc != CURSOR_MOVEMENT_SUCCESS
19232 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19233 {
19234
19235
19236
19237
19238
19239
19240
19241 bool rv = false;
19242 bool pt_invis = false;
19243 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19244 Qinvisible,
19245 Qnil, NULL);
19246
19247 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19248 pt_invis = true;
19249
19250 do
19251 {
19252 bool at_zv_p = false, exact_match_p = false;
19253
19254
19255
19256
19257
19258 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19259 && PT <= MATRIX_ROW_END_CHARPOS (row)
19260 && cursor_row_p (row))
19261 rv |= set_cursor_from_row (w, row, w->current_matrix,
19262 0, 0, 0, 0);
19263
19264
19265
19266 if (rv)
19267 {
19268 at_zv_p = MATRIX_ROW (w->current_matrix,
19269 w->cursor.vpos)->ends_at_zv_p;
19270 if (!at_zv_p
19271 && w->cursor.hpos >= 0
19272 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19273 w->cursor.vpos))
19274 {
19275 struct glyph_row *candidate =
19276 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19277 struct glyph *g =
19278 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19279 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19280
19281 exact_match_p =
19282 (BUFFERP (g->object) && g->charpos == PT)
19283 || (NILP (g->object)
19284 && (g->charpos == PT
19285 || (g->charpos == 0 && endpos - 1 == PT)));
19286
19287
19288
19289
19290 if (!exact_match_p && pt_invis)
19291 exact_match_p = true;
19292 }
19293 if (at_zv_p || exact_match_p)
19294 {
19295 rc = CURSOR_MOVEMENT_SUCCESS;
19296 break;
19297 }
19298 }
19299 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19300 break;
19301 ++row;
19302 }
19303 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19304 || row->continued_p)
19305 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19306 || (MATRIX_ROW_START_CHARPOS (row) == PT
19307 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19308
19309
19310
19311 if (rc != CURSOR_MOVEMENT_SUCCESS
19312 && !(rv
19313 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19314 && !row->continued_p))
19315 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19316 else if (rv)
19317 rc = CURSOR_MOVEMENT_SUCCESS;
19318 }
19319 else
19320 {
19321 do
19322 {
19323 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19324 {
19325 rc = CURSOR_MOVEMENT_SUCCESS;
19326 break;
19327 }
19328 ++row;
19329 }
19330 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19331 && MATRIX_ROW_START_CHARPOS (row) == PT
19332 && cursor_row_p (row));
19333 }
19334 }
19335 }
19336
19337 return rc;
19338 }
19339
19340
19341 void
19342 set_vertical_scroll_bar (struct window *w)
19343 {
19344 ptrdiff_t start, end, whole;
19345
19346
19347
19348
19349
19350
19351
19352
19353 if (!MINI_WINDOW_P (w)
19354 || (w == XWINDOW (minibuf_window)
19355 && NILP (echo_area_buffer[0])))
19356 {
19357 struct buffer *buf = XBUFFER (w->contents);
19358
19359 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19360 start = marker_position (w->start) - BUF_BEGV (buf);
19361 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19362
19363
19364
19365
19366 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19367 {
19368 struct it it;
19369 struct text_pos start_pos;
19370 struct buffer *obuf = current_buffer;
19371
19372
19373
19374 set_buffer_internal_1 (XBUFFER (w->contents));
19375 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19376 start_display (&it, w, start_pos);
19377 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19378 MOVE_TO_X | MOVE_TO_Y);
19379 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19380 set_buffer_internal_1 (obuf);
19381 }
19382
19383 if (end < start)
19384 end = start;
19385 if (whole < (end - start))
19386 whole = end - start;
19387 }
19388 else
19389 start = end = whole = 0;
19390
19391
19392 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19393 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19394 (w, end - start, whole, start);
19395 }
19396
19397
19398 void
19399 set_horizontal_scroll_bar (struct window *w)
19400 {
19401 int start, end, whole, portion;
19402
19403 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19404 {
19405 struct buffer *b = XBUFFER (w->contents);
19406 struct buffer *old_buffer = NULL;
19407 struct it it;
19408 struct text_pos startp;
19409
19410 if (b != current_buffer)
19411 {
19412 old_buffer = current_buffer;
19413 set_buffer_internal (b);
19414 }
19415
19416 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19417 start_display (&it, w, startp);
19418 it.last_visible_x = INT_MAX;
19419 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19420 MOVE_TO_X | MOVE_TO_Y);
19421
19422
19423
19424
19425 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19426 end = start + window_box_width (w, TEXT_AREA);
19427 portion = end - start;
19428
19429
19430
19431
19432 whole = max (whole, end);
19433
19434 if (it.bidi_p)
19435 {
19436 Lisp_Object pdir;
19437
19438 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19439 if (EQ (pdir, Qright_to_left))
19440 {
19441 start = whole - end;
19442 end = start + portion;
19443 }
19444 }
19445
19446 if (old_buffer)
19447 set_buffer_internal (old_buffer);
19448 }
19449 else
19450 start = end = whole = portion = 0;
19451
19452 w->hscroll_whole = whole;
19453
19454
19455 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19456 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19457 (w, portion, whole, start);
19458 }
19459
19460
19461
19462 static bool
19463 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19464 {
19465 if (!make_window_start_visible)
19466 return true;
19467
19468 struct window *w = XWINDOW (window);
19469 struct frame *f = XFRAME (w->frame);
19470 Lisp_Object startpos = make_fixnum (startp);
19471 Lisp_Object invprop, disp_spec;
19472 struct text_pos ignored;
19473
19474
19475 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19476 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19477 return false;
19478
19479
19480 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19481 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19482 FRAME_WINDOW_P (f)) > 0)
19483 return false;
19484
19485 return true;
19486 }
19487
19488 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19489 0, 0, 0,
19490 doc:
19491
19492 )
19493 (void)
19494 {
19495 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19496 }
19497
19498
19499
19500
19501
19502
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512
19513
19514
19515
19516
19517
19518
19519
19520
19521
19522
19523
19524
19525
19526
19527
19528
19529
19530
19531
19532
19533
19534
19535
19536
19537
19538
19539
19540
19541
19542
19543
19544
19545
19546
19547
19548 static void
19549 redisplay_window (Lisp_Object window, bool just_this_one_p)
19550 {
19551 struct window *w = XWINDOW (window);
19552 struct frame *f = XFRAME (w->frame);
19553 struct buffer *buffer = XBUFFER (w->contents);
19554 struct buffer *old = current_buffer;
19555 struct text_pos lpoint, opoint, startp;
19556 bool update_mode_line;
19557 int tem;
19558 struct it it;
19559
19560 bool current_matrix_up_to_date_p = false;
19561 bool used_current_matrix_p = false;
19562
19563
19564 bool buffer_unchanged_p = false;
19565 bool temp_scroll_step = false;
19566 specpdl_ref count = SPECPDL_INDEX ();
19567 int rc;
19568 int centering_position = -1;
19569 bool last_line_misfit = false;
19570 ptrdiff_t beg_unchanged, end_unchanged;
19571 int frame_line_height, margin;
19572 bool use_desired_matrix;
19573 void *itdata = NULL;
19574
19575 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19576 opoint = lpoint;
19577
19578 #ifdef GLYPH_DEBUG
19579 *w->desired_matrix->method = 0;
19580 #endif
19581
19582 if (!just_this_one_p && needs_no_redisplay (w))
19583 return;
19584
19585
19586 eassert (XMARKER (w->start)->buffer == buffer);
19587 eassert (XMARKER (w->pointm)->buffer == buffer);
19588
19589 reconsider_clip_changes (w);
19590 frame_line_height = default_line_pixel_height (w);
19591 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19592
19593
19594
19595 update_mode_line = (w->update_mode_line
19596 || update_mode_lines
19597 || buffer->clip_changed
19598 || buffer->prevent_redisplay_optimizations_p);
19599
19600 if (!just_this_one_p)
19601
19602
19603 w->must_be_updated_p = true;
19604
19605 if (MINI_WINDOW_P (w))
19606 {
19607 if (w == XWINDOW (echo_area_window)
19608 && !NILP (echo_area_buffer[0]))
19609 {
19610 if (update_mode_line)
19611
19612
19613 goto finish_menu_bars;
19614 else
19615
19616 goto finish_scroll_bars;
19617 }
19618 else if ((w != XWINDOW (minibuf_window)
19619 || minibuf_level == 0)
19620
19621 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19622
19623
19624 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19625 {
19626
19627
19628 int yb = window_text_bottom_y (w);
19629 struct glyph_row *row;
19630 int y;
19631
19632 for (y = 0, row = w->desired_matrix->rows;
19633 y < yb;
19634 y += row->height, ++row)
19635 blank_row (w, row, y);
19636 goto finish_scroll_bars;
19637 }
19638 else if (minibuf_level >= 1)
19639 {
19640
19641
19642
19643 resize_mini_window (w, false);
19644 }
19645
19646 clear_glyph_matrix (w->desired_matrix);
19647 }
19648
19649
19650
19651
19652
19653 set_buffer_internal_1 (XBUFFER (w->contents));
19654
19655 current_matrix_up_to_date_p
19656 = (w->window_end_valid
19657 && !current_buffer->clip_changed
19658 && !current_buffer->prevent_redisplay_optimizations_p
19659 && !window_outdated (w)
19660 && !composition_break_at_point
19661 && !hscrolling_current_line_p (w));
19662
19663 beg_unchanged = BEG_UNCHANGED;
19664 end_unchanged = END_UNCHANGED;
19665
19666 SET_TEXT_POS (opoint, PT, PT_BYTE);
19667
19668 specbind (Qinhibit_point_motion_hooks, Qt);
19669
19670 buffer_unchanged_p
19671 = (w->window_end_valid
19672 && !current_buffer->clip_changed
19673 && !window_outdated (w));
19674
19675
19676
19677 if (windows_or_buffers_changed)
19678 {
19679
19680
19681 if (XMARKER (w->start)->buffer == current_buffer)
19682 compute_window_start_on_continuation_line (w);
19683
19684 w->window_end_valid = false;
19685
19686
19687 current_matrix_up_to_date_p = false;
19688 }
19689
19690
19691 CHECK_WINDOW_END (w);
19692 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19693 emacs_abort ();
19694 if (BYTEPOS (opoint) < CHARPOS (opoint))
19695 emacs_abort ();
19696
19697 if (mode_line_update_needed (w))
19698 update_mode_line = true;
19699
19700
19701
19702 if (!EQ (window, selected_window))
19703 {
19704 ptrdiff_t new_pt = marker_position (w->pointm);
19705 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19706
19707 if (new_pt < BEGV)
19708 {
19709 new_pt = BEGV;
19710 new_pt_byte = BEGV_BYTE;
19711 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19712 }
19713 else if (new_pt > (ZV - 1))
19714 {
19715 new_pt = ZV;
19716 new_pt_byte = ZV_BYTE;
19717 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19718 }
19719
19720
19721 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19722 }
19723
19724
19725
19726
19727
19728
19729 if (current_buffer->width_run_cache
19730 || (current_buffer->base_buffer
19731 && current_buffer->base_buffer->width_run_cache))
19732 {
19733 struct Lisp_Char_Table *disptab = buffer_display_table ();
19734
19735 if (! disptab_matches_widthtab
19736 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19737 {
19738 struct buffer *buf = current_buffer;
19739
19740 if (buf->base_buffer)
19741 buf = buf->base_buffer;
19742 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19743 recompute_width_table (current_buffer, disptab);
19744 }
19745 }
19746
19747
19748 if (!NILP (Vlong_line_threshold)
19749 && !current_buffer->long_line_optimizations_p
19750 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19751 || current_buffer->clip_changed))
19752 {
19753 ptrdiff_t cur, next, found, max = 0, threshold;
19754 threshold = XFIXNUM (Vlong_line_threshold);
19755 for (cur = BEGV; cur < ZV; cur = next)
19756 {
19757 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19758 &found, NULL, true);
19759 if (next - cur > max) max = next - cur;
19760 if (!found || max > threshold) break;
19761 }
19762 if (max > threshold)
19763 current_buffer->long_line_optimizations_p = true;
19764 }
19765
19766
19767 if (XMARKER (w->start)->buffer != current_buffer)
19768 goto recenter;
19769
19770 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19771
19772
19773
19774 if ((w->optional_new_start || window_frozen_p (w))
19775 && CHARPOS (startp) >= BEGV
19776 && CHARPOS (startp) <= ZV)
19777 {
19778 ptrdiff_t it_charpos;
19779
19780 w->optional_new_start = false;
19781 if (!w->force_start)
19782 {
19783 start_display (&it, w, startp);
19784 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19785 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19786
19787
19788 it_charpos = IT_CHARPOS (it);
19789
19790
19791
19792
19793
19794 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19795 {
19796 if (it_charpos == PT)
19797 w->force_start = true;
19798
19799 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19800 w->force_start = true;
19801 #ifdef GLYPH_DEBUG
19802 if (w->force_start)
19803 {
19804 if (window_frozen_p (w))
19805 debug_method_add (w, "set force_start from frozen window start");
19806 else
19807 debug_method_add (w, "set force_start from optional_new_start");
19808 }
19809 #endif
19810 }
19811 }
19812 }
19813
19814 force_start:
19815
19816
19817
19818 if (w->force_start)
19819 {
19820
19821 int new_vpos = -1;
19822
19823 w->force_start = false;
19824
19825
19826
19827
19828 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19829 w->vscroll = 0;
19830
19831 w->preserve_vscroll_p = false;
19832 w->window_end_valid = false;
19833
19834
19835 if (!buffer_unchanged_p)
19836 w->base_line_number = 0;
19837
19838
19839
19840
19841
19842
19843
19844
19845 if (!update_mode_line
19846 || ! NILP (Vwindow_scroll_functions))
19847 {
19848 update_mode_line = true;
19849 w->update_mode_line = true;
19850 startp = run_window_scroll_functions (window, startp);
19851 }
19852
19853 if (CHARPOS (startp) < BEGV)
19854 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19855 else if (CHARPOS (startp) > ZV)
19856 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19857
19858
19859
19860 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19861 goto ignore_start;
19862
19863
19864
19865
19866
19867
19868 clear_glyph_matrix (w->desired_matrix);
19869 if (!try_window (window, startp, 0))
19870 {
19871 w->force_start = true;
19872 clear_glyph_matrix (w->desired_matrix);
19873 goto need_larger_matrices;
19874 }
19875
19876 if (w->cursor.vpos < 0)
19877 {
19878
19879
19880
19881
19882
19883 struct glyph_row *r = NULL;
19884 Lisp_Object invprop =
19885 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
19886 Qnil, NULL);
19887
19888 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19889 {
19890 ptrdiff_t alt_pt;
19891 Lisp_Object invprop_end =
19892 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
19893 Qnil, Qnil);
19894
19895 if (FIXNATP (invprop_end))
19896 alt_pt = XFIXNAT (invprop_end);
19897 else
19898 alt_pt = ZV;
19899 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
19900 NULL, 0);
19901 }
19902 if (r)
19903 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
19904 else
19905 new_vpos = window_box_height (w) / 2;
19906 }
19907
19908 if (!cursor_row_fully_visible_p (w, false, false, false))
19909 {
19910
19911
19912 new_vpos = window_box_height (w);
19913
19914
19915
19916
19917
19918
19919 if (new_vpos >= w->cursor.y)
19920 {
19921 w->cursor.vpos = -1;
19922 clear_glyph_matrix (w->desired_matrix);
19923 goto try_to_scroll;
19924 }
19925 }
19926 else if (w->cursor.vpos >= 0)
19927 {
19928
19929
19930
19931 int pixel_margin = margin * frame_line_height;
19932 bool tab_line = window_wants_tab_line (w);
19933 bool header_line = window_wants_header_line (w);
19934
19935
19936
19937
19938
19939 if (w->cursor.vpos < margin + tab_line + header_line)
19940 {
19941 w->cursor.vpos = -1;
19942 clear_glyph_matrix (w->desired_matrix);
19943 goto try_to_scroll;
19944 }
19945 else
19946 {
19947 int window_height = window_box_height (w);
19948
19949 if (tab_line)
19950 window_height += CURRENT_TAB_LINE_HEIGHT (w);
19951 if (header_line)
19952 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
19953 if (w->cursor.y >= window_height - pixel_margin)
19954 {
19955 w->cursor.vpos = -1;
19956 clear_glyph_matrix (w->desired_matrix);
19957 goto try_to_scroll;
19958 }
19959 }
19960 }
19961
19962
19963
19964 if (new_vpos >= 0)
19965 {
19966 struct glyph_row *row;
19967
19968 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
19969 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
19970 && !row->ends_at_zv_p)
19971 ++row;
19972
19973 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
19974 MATRIX_ROW_START_BYTEPOS (row));
19975
19976 if (w != XWINDOW (selected_window))
19977 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
19978 else if (current_buffer == old)
19979 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19980
19981 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
19982
19983
19984
19985
19986
19987
19988
19989 w->redisplay = false;
19990 XBUFFER (w->contents)->text->redisplay = false;
19991 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
19992
19993 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
19994 || ((EQ (Vdisplay_line_numbers, Qrelative)
19995 || EQ (Vdisplay_line_numbers, Qvisual))
19996 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
19997 {
19998
19999
20000
20001
20002 clear_glyph_matrix (w->desired_matrix);
20003 if (!try_window (window, startp, 0))
20004 goto need_larger_matrices;
20005 }
20006 }
20007 if (w->cursor.vpos < 0
20008 || !cursor_row_fully_visible_p (w, false, false, false))
20009 {
20010 clear_glyph_matrix (w->desired_matrix);
20011 goto try_to_scroll;
20012 }
20013
20014 #ifdef GLYPH_DEBUG
20015 debug_method_add (w, "forced window start");
20016 #endif
20017 goto done;
20018 }
20019
20020 ignore_start:
20021
20022
20023
20024
20025 if (current_matrix_up_to_date_p
20026 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20027 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20028 {
20029 switch (rc)
20030 {
20031 case CURSOR_MOVEMENT_SUCCESS:
20032 used_current_matrix_p = true;
20033 goto done;
20034
20035 case CURSOR_MOVEMENT_MUST_SCROLL:
20036 goto try_to_scroll;
20037
20038 default:
20039 emacs_abort ();
20040 }
20041 }
20042
20043
20044
20045 else if (w->start_at_line_beg
20046 && ((CHARPOS (startp) > BEGV
20047 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20048 || (CHARPOS (startp) >= BEGV
20049 && CHARPOS (startp) <= ZV
20050 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20051 {
20052 #ifdef GLYPH_DEBUG
20053 debug_method_add (w, "recenter 1");
20054 #endif
20055 goto recenter;
20056 }
20057
20058
20059
20060
20061 else if ((tem = try_window_id (w)) != 0)
20062 {
20063 #ifdef GLYPH_DEBUG
20064 debug_method_add (w, "try_window_id %d", tem);
20065 #endif
20066
20067 if (f->fonts_changed)
20068 goto need_larger_matrices;
20069 if (tem > 0)
20070 goto done;
20071
20072
20073
20074 }
20075 else if (CHARPOS (startp) >= BEGV
20076 && CHARPOS (startp) <= ZV
20077 && PT >= CHARPOS (startp)
20078 && (CHARPOS (startp) < ZV
20079
20080 || CHARPOS (startp) == BEGV
20081 || !window_outdated (w)))
20082 {
20083 int d1, d2, d5, d6;
20084 int rtop, rbot;
20085
20086
20087
20088
20089
20090
20091
20092
20093
20094
20095 if (!w->start_at_line_beg
20096 && NILP (track_mouse)
20097 && CHARPOS (startp) > BEGV
20098 && CHARPOS (startp) > BEG + beg_unchanged
20099 && CHARPOS (startp) <= Z - end_unchanged
20100
20101
20102
20103
20104
20105 && XMARKER (w->start)->buffer == current_buffer
20106 && compute_window_start_on_continuation_line (w)
20107
20108
20109
20110
20111
20112
20113 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20114
20115
20116 && (rtop != 0) == (rbot != 0))
20117 {
20118 w->force_start = true;
20119 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20120 #ifdef GLYPH_DEBUG
20121 debug_method_add (w, "recomputed window start in continuation line");
20122 #endif
20123 goto force_start;
20124 }
20125
20126
20127
20128
20129 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20130 {
20131 #ifdef GLYPH_DEBUG
20132 debug_method_add (w, "recenter 2");
20133 #endif
20134 goto recenter;
20135 }
20136
20137 #ifdef GLYPH_DEBUG
20138 debug_method_add (w, "same window start");
20139 #endif
20140
20141
20142
20143 if (!current_matrix_up_to_date_p
20144
20145
20146
20147 || !NILP (Vwindow_scroll_functions)
20148 || MINI_WINDOW_P (w)
20149 || !(used_current_matrix_p
20150 = try_window_reusing_current_matrix (w)))
20151 {
20152 IF_DEBUG (debug_method_add (w, "1"));
20153 clear_glyph_matrix (w->desired_matrix);
20154 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20155
20156
20157
20158 goto try_to_scroll;
20159 }
20160
20161 if (f->fonts_changed)
20162 goto need_larger_matrices;
20163
20164 if (w->cursor.vpos >= 0)
20165 {
20166 if (!just_this_one_p
20167 || current_buffer->clip_changed
20168 || BEG_UNCHANGED < CHARPOS (startp))
20169
20170 w->base_line_number = 0;
20171
20172 if (!cursor_row_fully_visible_p (w, true, false, false))
20173 {
20174 clear_glyph_matrix (w->desired_matrix);
20175 last_line_misfit = true;
20176 }
20177
20178 else
20179 goto done;
20180 }
20181 else
20182 clear_glyph_matrix (w->desired_matrix);
20183 }
20184
20185 try_to_scroll:
20186
20187
20188 if (!update_mode_line)
20189 {
20190 update_mode_line = true;
20191 w->update_mode_line = true;
20192 }
20193
20194
20195 if ((0 < scroll_conservatively
20196
20197
20198
20199
20200 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20201 || 0 < emacs_scroll_step
20202 || temp_scroll_step
20203 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20204 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20205 && CHARPOS (startp) >= BEGV
20206 && CHARPOS (startp) <= ZV)
20207 {
20208
20209
20210 int ss = try_scrolling (window, just_this_one_p,
20211 ((scroll_minibuffer_conservatively
20212 && MINI_WINDOW_P (w))
20213 ? SCROLL_LIMIT + 1
20214 : scroll_conservatively),
20215 emacs_scroll_step,
20216 temp_scroll_step, last_line_misfit);
20217 switch (ss)
20218 {
20219 case SCROLLING_SUCCESS:
20220 goto done;
20221
20222 case SCROLLING_NEED_LARGER_MATRICES:
20223 goto need_larger_matrices;
20224
20225 case SCROLLING_FAILED:
20226 break;
20227
20228 default:
20229 emacs_abort ();
20230 }
20231 }
20232
20233
20234
20235
20236 recenter:
20237
20238 #ifdef GLYPH_DEBUG
20239 debug_method_add (w, "recenter");
20240 #endif
20241
20242
20243 if (!buffer_unchanged_p)
20244 w->base_line_number = 0;
20245
20246
20247 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20248 it.current_y = it.last_visible_y;
20249 if (centering_position < 0)
20250 {
20251 ptrdiff_t margin_pos = CHARPOS (startp);
20252 Lisp_Object aggressive;
20253 bool scrolling_up;
20254
20255
20256
20257 if (margin
20258
20259
20260
20261
20262
20263
20264 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20265 {
20266 struct it it1;
20267 void *it1data = NULL;
20268
20269 SAVE_IT (it1, it, it1data);
20270 start_display (&it1, w, startp);
20271 move_it_vertically (&it1, margin * frame_line_height);
20272 margin_pos = IT_CHARPOS (it1);
20273 RESTORE_IT (&it, &it, it1data);
20274 }
20275 scrolling_up = PT > margin_pos;
20276 aggressive =
20277 scrolling_up
20278 ? BVAR (current_buffer, scroll_up_aggressively)
20279 : BVAR (current_buffer, scroll_down_aggressively);
20280
20281 if (!MINI_WINDOW_P (w)
20282 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20283 {
20284 int pt_offset = 0;
20285
20286
20287
20288 if (!scroll_conservatively && NUMBERP (aggressive))
20289 {
20290 double float_amount = XFLOATINT (aggressive);
20291
20292 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20293 if (pt_offset == 0 && float_amount > 0)
20294 pt_offset = 1;
20295 if (pt_offset && margin > 0)
20296 margin -= 1;
20297 }
20298
20299
20300
20301 if (scrolling_up)
20302 {
20303 centering_position = it.last_visible_y;
20304 if (pt_offset)
20305 centering_position -= pt_offset;
20306 centering_position -=
20307 (frame_line_height * (1 + margin + last_line_misfit)
20308 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20309
20310
20311 if (centering_position < margin * frame_line_height)
20312 centering_position = margin * frame_line_height;
20313 }
20314 else
20315 centering_position = margin * frame_line_height + pt_offset;
20316 }
20317 else
20318
20319
20320 centering_position = window_box_height (w) / 2;
20321 }
20322 if (current_buffer->long_line_optimizations_p
20323 && it.line_wrap == TRUNCATE)
20324 {
20325
20326
20327
20328 int nlines = centering_position / frame_line_height;
20329
20330 while (nlines-- && IT_CHARPOS (it) > BEGV)
20331 back_to_previous_visible_line_start (&it);
20332 reseat_1 (&it, it.current.pos, true);
20333 }
20334 else
20335 move_it_vertically_backward (&it, centering_position);
20336
20337 eassert (IT_CHARPOS (it) >= BEGV);
20338
20339
20340
20341
20342
20343
20344 if (it.current_y <= 0)
20345 {
20346 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20347 move_it_vertically_backward (&it, 0);
20348 it.current_y = 0;
20349 }
20350
20351 it.current_x = it.hpos = 0;
20352
20353
20354
20355
20356 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20357
20358
20359 startp = run_window_scroll_functions (window, it.current.pos);
20360
20361
20362
20363
20364 itdata = bidi_shelve_cache ();
20365
20366
20367 use_desired_matrix = false;
20368 if (!current_matrix_up_to_date_p
20369 || windows_or_buffers_changed
20370 || f->cursor_type_changed
20371
20372
20373 || !NILP (Vwindow_scroll_functions)
20374 || !just_this_one_p
20375 || MINI_WINDOW_P (w)
20376 || !(used_current_matrix_p
20377 = try_window_reusing_current_matrix (w)))
20378 use_desired_matrix = (try_window (window, startp, 0) == 1);
20379
20380 bidi_unshelve_cache (itdata, false);
20381
20382
20383
20384
20385 if (f->fonts_changed)
20386 goto need_larger_matrices;
20387
20388
20389
20390
20391
20392
20393 if (w->cursor.vpos < 0)
20394 {
20395 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20396 {
20397 clear_glyph_matrix (w->desired_matrix);
20398 move_it_by_lines (&it, 1);
20399 try_window (window, it.current.pos, 0);
20400 }
20401 else if (PT < IT_CHARPOS (it))
20402 {
20403 clear_glyph_matrix (w->desired_matrix);
20404 move_it_by_lines (&it, -1);
20405 try_window (window, it.current.pos, 0);
20406 }
20407 else if (scroll_conservatively > SCROLL_LIMIT
20408 && (it.method == GET_FROM_STRING
20409 || overlay_touches_p (IT_CHARPOS (it)))
20410 && IT_CHARPOS (it) < ZV)
20411 {
20412
20413
20414
20415
20416
20417
20418
20419
20420 ptrdiff_t pos0 = IT_CHARPOS (it);
20421
20422 clear_glyph_matrix (w->desired_matrix);
20423 do {
20424 move_it_by_lines (&it, 1);
20425 } while (IT_CHARPOS (it) == pos0);
20426 try_window (window, it.current.pos, 0);
20427 }
20428 else
20429 {
20430
20431 }
20432 }
20433
20434
20435
20436
20437
20438
20439 if (w->cursor.vpos < 0)
20440 {
20441
20442
20443
20444
20445 struct glyph_matrix *matrix =
20446 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20447
20448 struct glyph_row *row =
20449 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20450
20451
20452
20453
20454
20455
20456
20457 if (!row)
20458 {
20459 Lisp_Object val =
20460 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20461 Qnil, NULL);
20462
20463 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20464 {
20465 ptrdiff_t alt_pos;
20466 Lisp_Object invis_end =
20467 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20468 Qnil, Qnil);
20469
20470 if (FIXNATP (invis_end))
20471 alt_pos = XFIXNAT (invis_end);
20472 else
20473 alt_pos = ZV;
20474 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20475 }
20476 }
20477
20478
20479
20480 if (!row)
20481 {
20482 row = matrix->rows;
20483
20484 if (row->tab_line_p)
20485 ++row;
20486 if (row->mode_line_p)
20487 ++row;
20488 }
20489 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20490 }
20491
20492 if (!cursor_row_fully_visible_p (w, false, false, false))
20493 {
20494
20495 if (w->vscroll)
20496 {
20497 w->vscroll = 0;
20498 clear_glyph_matrix (w->desired_matrix);
20499 goto recenter;
20500 }
20501
20502
20503
20504
20505
20506 if (scroll_conservatively > SCROLL_LIMIT)
20507 {
20508 int window_total_lines
20509 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20510 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20511
20512 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20513 clear_glyph_matrix (w->desired_matrix);
20514 if (1 == try_window (window, it.current.pos,
20515 TRY_WINDOW_CHECK_MARGINS))
20516 goto done;
20517 }
20518
20519
20520
20521
20522 if (centering_position == 0)
20523 goto done;
20524
20525 clear_glyph_matrix (w->desired_matrix);
20526 centering_position = 0;
20527 goto recenter;
20528 }
20529
20530 done:
20531
20532 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20533 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20534 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20535
20536
20537 if ((update_mode_line
20538
20539
20540
20541
20542 || (!just_this_one_p
20543 && !FRAME_WINDOW_P (f)
20544 && !WINDOW_FULL_WIDTH_P (w))
20545
20546 || w->base_line_pos > 0
20547
20548 || (w->column_number_displayed != -1
20549 && (w->column_number_displayed != current_column ())))
20550
20551 && (window_wants_mode_line (w)
20552 || window_wants_header_line (w)
20553 || window_wants_tab_line (w)))
20554 {
20555 specpdl_ref count1 = SPECPDL_INDEX ();
20556
20557 specbind (Qinhibit_quit, Qt);
20558 display_mode_lines (w);
20559 unbind_to (count1, Qnil);
20560
20561
20562
20563 if (window_wants_mode_line (w)
20564 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20565 {
20566 f->fonts_changed = true;
20567 w->mode_line_height = -1;
20568 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20569 = DESIRED_MODE_LINE_HEIGHT (w);
20570 }
20571
20572
20573
20574 if (window_wants_tab_line (w)
20575 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20576 {
20577 f->fonts_changed = true;
20578 w->tab_line_height = -1;
20579 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20580 = DESIRED_TAB_LINE_HEIGHT (w);
20581 }
20582
20583
20584
20585 if (window_wants_header_line (w)
20586 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20587 {
20588 f->fonts_changed = true;
20589 w->header_line_height = -1;
20590 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20591 = DESIRED_HEADER_LINE_HEIGHT (w);
20592 }
20593
20594 if (f->fonts_changed)
20595 goto need_larger_matrices;
20596 }
20597
20598 if (!line_number_displayed && w->base_line_pos != -1)
20599 {
20600 w->base_line_pos = 0;
20601 w->base_line_number = 0;
20602 }
20603
20604 finish_menu_bars:
20605
20606
20607
20608 if (update_mode_line
20609 && EQ (FRAME_SELECTED_WINDOW (f), window))
20610 {
20611 bool redisplay_menu_p;
20612
20613 if (FRAME_WINDOW_P (f))
20614 {
20615 #ifdef HAVE_EXT_MENU_BAR
20616 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20617 #else
20618 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20619 #endif
20620 }
20621 else
20622 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20623
20624 if (redisplay_menu_p)
20625 display_menu_bar (w);
20626
20627 #ifdef HAVE_WINDOW_SYSTEM
20628 if (FRAME_WINDOW_P (f))
20629 {
20630 if (WINDOWP (f->tab_bar_window)
20631 && (FRAME_TAB_BAR_LINES (f) > 0
20632 || !NILP (Vauto_resize_tab_bars))
20633 && redisplay_tab_bar (f))
20634 ignore_mouse_drag_p = true;
20635
20636 #ifdef HAVE_EXT_TOOL_BAR
20637 if (FRAME_EXTERNAL_TOOL_BAR (f))
20638 update_frame_tool_bar (f);
20639 #else
20640 if (WINDOWP (f->tool_bar_window)
20641 && (FRAME_TOOL_BAR_LINES (f) > 0
20642 || !NILP (Vauto_resize_tool_bars))
20643 && redisplay_tool_bar (f))
20644 ignore_mouse_drag_p = true;
20645 #endif
20646 }
20647 else
20648 {
20649 if ((FRAME_TAB_BAR_LINES (f) > 0))
20650 display_tab_bar (w);
20651 }
20652
20653 gui_consider_frame_title (w->frame);
20654 #else
20655 if ((FRAME_TAB_BAR_LINES (f) > 0))
20656 display_tab_bar (w);
20657 #endif
20658 }
20659
20660 #ifdef HAVE_WINDOW_SYSTEM
20661 if (FRAME_WINDOW_P (f)
20662 && update_window_fringes (w, (just_this_one_p
20663 || (!used_current_matrix_p && !overlay_arrow_seen)
20664 || w->pseudo_window_p)))
20665 {
20666 update_begin (f);
20667 block_input ();
20668 if (draw_window_fringes (w, true))
20669 {
20670 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20671 gui_draw_right_divider (w);
20672 else
20673 gui_draw_vertical_border (w);
20674 }
20675 unblock_input ();
20676 update_end (f);
20677 }
20678
20679 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20680 gui_draw_bottom_divider (w);
20681 #endif
20682
20683
20684
20685
20686
20687 need_larger_matrices:
20688 ;
20689 finish_scroll_bars:
20690
20691 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20692 {
20693 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20694
20695 set_vertical_scroll_bar (w);
20696
20697 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20698
20699 set_horizontal_scroll_bar (w);
20700
20701
20702
20703 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20704 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20705 }
20706
20707
20708
20709
20710 if (CHARPOS (opoint) < BEGV)
20711 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20712 else if (CHARPOS (opoint) > ZV)
20713 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20714 else
20715 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20716
20717 set_buffer_internal_1 (old);
20718
20719
20720 if (CHARPOS (lpoint) <= ZV)
20721 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20722
20723 unbind_to (count, Qnil);
20724 }
20725
20726
20727
20728
20729
20730
20731
20732
20733
20734
20735
20736
20737
20738
20739
20740
20741
20742
20743
20744
20745 int
20746 try_window (Lisp_Object window, struct text_pos pos, int flags)
20747 {
20748 struct window *w = XWINDOW (window);
20749 struct it it;
20750 struct glyph_row *last_text_row = NULL;
20751 struct frame *f = XFRAME (w->frame);
20752 int cursor_vpos = w->cursor.vpos;
20753
20754
20755 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20756
20757
20758 w->cursor.vpos = -1;
20759 overlay_arrow_seen = false;
20760
20761
20762 start_display (&it, w, pos);
20763 it.glyph_row->reversed_p = false;
20764
20765
20766 while (it.current_y < it.last_visible_y)
20767 {
20768 int last_row_scale = it.w->nrows_scale_factor;
20769 int last_col_scale = it.w->ncols_scale_factor;
20770 if (display_line (&it, cursor_vpos))
20771 last_text_row = it.glyph_row - 1;
20772 if (f->fonts_changed
20773 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20774
20775
20776 && last_row_scale == it.w->nrows_scale_factor
20777 && last_col_scale == it.w->ncols_scale_factor))
20778 return 0;
20779 }
20780
20781
20782
20783 ptrdiff_t it_charpos = IT_CHARPOS (it);
20784
20785
20786
20787
20788 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20789 && w->vscroll == 0
20790 && !MINI_WINDOW_P (w))
20791 {
20792 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20793 int bot_scroll_margin = top_scroll_margin;
20794 if (window_wants_header_line (w))
20795 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20796 if (window_wants_tab_line (w))
20797 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20798 start_display (&it, w, pos);
20799
20800 if ((w->cursor.y >= 0
20801 && w->cursor.y < top_scroll_margin
20802 && CHARPOS (pos) > BEGV)
20803
20804
20805
20806
20807 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20808 - bot_scroll_margin - 1))
20809 {
20810 w->cursor.vpos = -1;
20811 clear_glyph_matrix (w->desired_matrix);
20812 return -1;
20813 }
20814 }
20815
20816
20817 if (w->window_end_pos <= 0 && Z != it_charpos)
20818 w->update_mode_line = true;
20819
20820
20821
20822
20823 if (last_text_row)
20824 {
20825 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20826 adjust_window_ends (w, last_text_row, false);
20827 eassert
20828 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20829 w->window_end_vpos)));
20830 }
20831 else
20832 {
20833 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20834 w->window_end_pos = Z - ZV;
20835 w->window_end_vpos = 0;
20836 }
20837
20838
20839 w->window_end_valid = false;
20840 return 1;
20841 }
20842
20843
20844
20845
20846
20847
20848
20849
20850
20851
20852
20853
20854 static bool
20855 try_window_reusing_current_matrix (struct window *w)
20856 {
20857 struct frame *f = XFRAME (w->frame);
20858 struct glyph_row *bottom_row;
20859 struct it it;
20860 struct run run;
20861 struct text_pos start, new_start;
20862 int nrows_scrolled, i;
20863 struct glyph_row *last_text_row;
20864 struct glyph_row *last_reused_text_row;
20865 struct glyph_row *start_row;
20866 int start_vpos, min_y, max_y;
20867
20868 #ifdef GLYPH_DEBUG
20869 if (inhibit_try_window_reusing)
20870 return false;
20871 #endif
20872
20873 if (
20874 !FRAME_WINDOW_P (f)
20875
20876
20877 || windows_or_buffers_changed
20878 || f->cursor_type_changed
20879
20880
20881
20882 || overlay_arrow_in_current_buffer_p ())
20883 return false;
20884
20885
20886 if (!NILP (Vshow_trailing_whitespace))
20887 return false;
20888
20889
20890 if (window_wants_tab_line (w)
20891 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
20892 return false;
20893
20894
20895 if (window_wants_header_line (w)
20896 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
20897 return false;
20898
20899
20900
20901 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20902 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
20903 return false;
20904
20905
20906 clear_glyph_matrix (w->desired_matrix);
20907
20908
20909
20910
20911 if (!NILP (Vdisplay_line_numbers))
20912 return false;
20913
20914
20915
20916
20917 #ifdef HAVE_NTGUI
20918 if (w32_use_visible_system_caret)
20919 return false;
20920 #endif
20921
20922
20923
20924 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
20925 start = start_row->minpos;
20926 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20927
20928 if (CHARPOS (new_start) <= CHARPOS (start))
20929 {
20930
20931
20932
20933
20934 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
20935 return false;
20936
20937 IF_DEBUG (debug_method_add (w, "twu1"));
20938
20939
20940
20941
20942
20943 start_display (&it, w, new_start);
20944 w->cursor.vpos = -1;
20945 last_text_row = last_reused_text_row = NULL;
20946
20947 while (it.current_y < it.last_visible_y && !f->fonts_changed)
20948 {
20949
20950
20951
20952
20953 while (IT_CHARPOS (it) > CHARPOS (start))
20954 {
20955
20956 start_row++;
20957 start = start_row->minpos;
20958
20959 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
20960 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
20961 || CHARPOS (start) == ZV)
20962 {
20963 clear_glyph_matrix (w->desired_matrix);
20964 return false;
20965 }
20966
20967 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20968 }
20969
20970
20971 if (IT_CHARPOS (it) == CHARPOS (start)
20972
20973
20974
20975
20976
20977 && it.current.dpvec_index < 0)
20978 break;
20979
20980 it.glyph_row->reversed_p = false;
20981 if (display_line (&it, -1))
20982 last_text_row = it.glyph_row - 1;
20983
20984 }
20985
20986
20987
20988
20989 if (it.current_y < it.last_visible_y)
20990 {
20991 struct glyph_row *row;
20992
20993
20994 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
20995
20996
20997 if (w->cursor.vpos < 0)
20998 {
20999 int dy = it.current_y - start_row->y;
21000
21001 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21002 row = row_containing_pos (w, PT, row, NULL, dy);
21003 if (row)
21004 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21005 dy, nrows_scrolled);
21006 else
21007 {
21008 clear_glyph_matrix (w->desired_matrix);
21009 return false;
21010 }
21011 }
21012
21013
21014
21015
21016
21017
21018
21019 run.current_y = start_row->y;
21020 run.desired_y = it.current_y;
21021 run.height = it.last_visible_y - it.current_y;
21022
21023 if (run.height > 0 && run.current_y != run.desired_y)
21024 {
21025 #ifdef HAVE_WINDOW_SYSTEM
21026 update_begin (f);
21027 gui_update_window_begin (w);
21028 FRAME_RIF (f)->clear_window_mouse_face (w);
21029 FRAME_RIF (f)->scroll_run_hook (w, &run);
21030 gui_update_window_end (w, false, false);
21031 update_end (f);
21032 #endif
21033 }
21034
21035
21036 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21037 rotate_matrix (w->current_matrix,
21038 start_vpos,
21039 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21040 nrows_scrolled);
21041
21042
21043 for (i = 0; i < nrows_scrolled; ++i)
21044 (start_row + i)->enabled_p = false;
21045
21046
21047 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21048 max_y = it.last_visible_y;
21049 for (row = start_row + nrows_scrolled;
21050 row < bottom_row;
21051 ++row)
21052 {
21053 row->y = it.current_y;
21054 row->visible_height = row->height;
21055
21056 if (row->y < min_y)
21057 row->visible_height -= min_y - row->y;
21058 if (row->y + row->height > max_y)
21059 row->visible_height -= row->y + row->height - max_y;
21060 if (row->fringe_bitmap_periodic_p)
21061 row->redraw_fringe_bitmaps_p = true;
21062
21063 it.current_y += row->height;
21064
21065 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21066 last_reused_text_row = row;
21067 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21068 break;
21069 }
21070
21071
21072
21073 for (++row; row < bottom_row; ++row)
21074 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21075 }
21076
21077
21078
21079
21080
21081 if (last_reused_text_row)
21082 adjust_window_ends (w, last_reused_text_row, true);
21083 else if (last_text_row)
21084 adjust_window_ends (w, last_text_row, false);
21085 else
21086 {
21087
21088 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21089 w->window_end_pos = Z - ZV;
21090 w->window_end_vpos = 0;
21091 }
21092 w->window_end_valid = false;
21093
21094
21095 w->desired_matrix->no_scrolling_p = true;
21096
21097 #ifdef GLYPH_DEBUG
21098 debug_method_add (w, "try_window_reusing_current_matrix 1");
21099 #endif
21100 return true;
21101 }
21102 else if (CHARPOS (new_start) > CHARPOS (start))
21103 {
21104 struct glyph_row *pt_row, *row;
21105 struct glyph_row *first_reusable_row;
21106 struct glyph_row *first_row_to_display;
21107 int dy;
21108 int yb = window_text_bottom_y (w);
21109
21110
21111
21112 first_reusable_row = start_row;
21113 while (first_reusable_row->enabled_p
21114 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21115 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21116 < CHARPOS (new_start)))
21117 ++first_reusable_row;
21118
21119
21120 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21121 || !first_reusable_row->enabled_p
21122 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21123 != CHARPOS (new_start)))
21124 return false;
21125
21126
21127
21128
21129
21130 pt_row = NULL;
21131 for (first_row_to_display = first_reusable_row;
21132 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21133 ++first_row_to_display)
21134 {
21135 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21136 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21137 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21138 && first_row_to_display->ends_at_zv_p
21139 && pt_row == NULL)))
21140 pt_row = first_row_to_display;
21141 }
21142
21143 if (first_row_to_display->y >= yb)
21144 return false;
21145
21146
21147 init_to_row_start (&it, w, first_row_to_display);
21148
21149 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21150 - start_vpos);
21151 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21152 - nrows_scrolled);
21153 it.current_y = (first_row_to_display->y - first_reusable_row->y
21154 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21155
21156
21157
21158
21159 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21160 if (pt_row == NULL)
21161 w->cursor.vpos = -1;
21162 last_text_row = NULL;
21163 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21164 if (display_line (&it, w->cursor.vpos))
21165 last_text_row = it.glyph_row - 1;
21166
21167
21168
21169 if (pt_row)
21170 {
21171 w->cursor.vpos -= nrows_scrolled;
21172 w->cursor.y -= first_reusable_row->y - start_row->y;
21173 }
21174
21175
21176
21177
21178
21179 if (w->cursor.vpos < 0)
21180 {
21181 clear_glyph_matrix (w->desired_matrix);
21182 return false;
21183 }
21184
21185
21186 run.current_y = first_reusable_row->y;
21187 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21188 run.height = it.last_visible_y - run.current_y;
21189 dy = run.current_y - run.desired_y;
21190
21191 if (run.height)
21192 {
21193 #ifdef HAVE_WINDOW_SYSTEM
21194 update_begin (f);
21195 gui_update_window_begin (w);
21196 FRAME_RIF (f)->clear_window_mouse_face (w);
21197 FRAME_RIF (f)->scroll_run_hook (w, &run);
21198 gui_update_window_end (w, false, false);
21199 update_end (f);
21200 #endif
21201 }
21202
21203
21204 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21205 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21206 max_y = it.last_visible_y;
21207 for (row = first_reusable_row; row < first_row_to_display; ++row)
21208 {
21209 row->y -= dy;
21210 row->visible_height = row->height;
21211 if (row->y < min_y)
21212 row->visible_height -= min_y - row->y;
21213 if (row->y + row->height > max_y)
21214 row->visible_height -= row->y + row->height - max_y;
21215 if (row->fringe_bitmap_periodic_p)
21216 row->redraw_fringe_bitmaps_p = true;
21217 }
21218
21219
21220 eassert (nrows_scrolled > 0);
21221 rotate_matrix (w->current_matrix,
21222 start_vpos,
21223 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21224 -nrows_scrolled);
21225
21226
21227 for (row -= nrows_scrolled; row < bottom_row; ++row)
21228 row->enabled_p = false;
21229
21230
21231
21232 if (pt_row)
21233 {
21234 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21235 row < bottom_row
21236 && PT >= MATRIX_ROW_END_CHARPOS (row)
21237 && !row->ends_at_zv_p;
21238 row++)
21239 {
21240 w->cursor.vpos++;
21241 w->cursor.y = row->y;
21242 }
21243 if (row < bottom_row)
21244 {
21245
21246
21247
21248
21249 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21250 {
21251 if (!set_cursor_from_row (w, row, w->current_matrix,
21252 0, 0, 0, 0))
21253 {
21254 clear_glyph_matrix (w->desired_matrix);
21255 return false;
21256 }
21257 }
21258 else
21259 {
21260 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21261 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21262
21263 for (; glyph < end
21264 && (!BUFFERP (glyph->object)
21265 || glyph->charpos < PT);
21266 glyph++)
21267 {
21268 w->cursor.hpos++;
21269 w->cursor.x += glyph->pixel_width;
21270 }
21271 }
21272 }
21273 }
21274
21275
21276
21277
21278 if (last_text_row)
21279 adjust_window_ends (w, last_text_row, false);
21280 else
21281 w->window_end_vpos -= nrows_scrolled;
21282
21283 w->window_end_valid = false;
21284 w->desired_matrix->no_scrolling_p = true;
21285
21286 #ifdef GLYPH_DEBUG
21287 debug_method_add (w, "try_window_reusing_current_matrix 2");
21288 #endif
21289 return true;
21290 }
21291
21292 return false;
21293 }
21294
21295
21296
21297
21298
21299
21300
21301 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21302 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21303 ptrdiff_t *, ptrdiff_t *);
21304 static struct glyph_row *
21305 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21306 struct glyph_row *);
21307
21308
21309
21310
21311
21312
21313
21314 static struct glyph_row *
21315 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21316 struct glyph_row *start)
21317 {
21318 struct glyph_row *row, *row_found;
21319
21320
21321
21322
21323 row_found = NULL;
21324 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21325 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21326 {
21327 eassert (row->enabled_p);
21328 row_found = row;
21329 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21330 break;
21331 ++row;
21332 }
21333
21334 return row_found;
21335 }
21336
21337
21338
21339
21340
21341
21342
21343
21344
21345
21346
21347
21348 static struct glyph_row *
21349 find_last_unchanged_at_beg_row (struct window *w)
21350 {
21351 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21352 struct glyph_row *row;
21353 struct glyph_row *row_found = NULL;
21354 int yb = window_text_bottom_y (w);
21355
21356
21357 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21358 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21359 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21360 ++row)
21361 {
21362 if (
21363
21364 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21365
21366
21367 && !row->ends_at_zv_p
21368
21369
21370
21371 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21372 && (row->continued_p
21373 || row->exact_window_width_line_p))
21374
21375
21376
21377
21378
21379
21380
21381 && CHARPOS (row->end.pos) <= ZV)
21382 row_found = row;
21383
21384
21385 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21386 break;
21387 }
21388
21389 return row_found;
21390 }
21391
21392
21393
21394
21395
21396
21397
21398
21399
21400
21401
21402
21403
21404
21405 static struct glyph_row *
21406 find_first_unchanged_at_end_row (struct window *w,
21407 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21408 {
21409 struct glyph_row *row;
21410 struct glyph_row *row_found = NULL;
21411
21412 *delta = *delta_bytes = 0;
21413
21414
21415
21416 eassert (w->window_end_valid);
21417
21418
21419
21420
21421 if (w->window_end_pos >= END_UNCHANGED)
21422 return NULL;
21423
21424
21425 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21426
21427
21428 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21429 {
21430
21431
21432
21433
21434
21435 ptrdiff_t Z_old =
21436 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21437 ptrdiff_t Z_BYTE_old =
21438 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21439 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21440 struct glyph_row *first_text_row
21441 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21442
21443 *delta = Z - Z_old;
21444 *delta_bytes = Z_BYTE - Z_BYTE_old;
21445
21446
21447
21448
21449
21450
21451
21452 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21453 last_unchanged_pos_old = last_unchanged_pos - *delta;
21454
21455
21456
21457 for (; row > first_text_row; --row)
21458 {
21459
21460
21461 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21462 break;
21463
21464 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21465 row_found = row;
21466 }
21467 }
21468
21469 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21470
21471 return row_found;
21472 }
21473
21474
21475
21476
21477
21478
21479
21480
21481 static void
21482 sync_frame_with_window_matrix_rows (struct window *w)
21483 {
21484 struct frame *f = XFRAME (w->frame);
21485 struct glyph_row *window_row, *window_row_end, *frame_row;
21486
21487
21488
21489 eassert (BUFFERP (w->contents));
21490 eassert (WINDOW_FULL_WIDTH_P (w));
21491 eassert (!FRAME_WINDOW_P (f));
21492
21493
21494
21495
21496
21497 window_row = w->current_matrix->rows;
21498 window_row_end = window_row + w->current_matrix->nrows;
21499 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21500 while (window_row < window_row_end)
21501 {
21502 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21503 struct glyph *end = window_row->glyphs[LAST_AREA];
21504
21505 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21506 frame_row->glyphs[TEXT_AREA] = start;
21507 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21508 frame_row->glyphs[LAST_AREA] = end;
21509
21510
21511
21512 if (!window_row->enabled_p)
21513 frame_row->enabled_p = false;
21514
21515 ++window_row, ++frame_row;
21516 }
21517 }
21518
21519
21520
21521
21522
21523
21524
21525 struct glyph_row *
21526 row_containing_pos (struct window *w, ptrdiff_t charpos,
21527 struct glyph_row *start, struct glyph_row *end, int dy)
21528 {
21529 struct glyph_row *row = start;
21530 struct glyph_row *best_row = NULL;
21531 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21532 int last_y;
21533
21534
21535 if (row->tab_line_p)
21536 ++row;
21537 if (row->mode_line_p)
21538 ++row;
21539
21540 if ((end && row >= end) || !row->enabled_p)
21541 return NULL;
21542
21543 last_y = window_text_bottom_y (w) - dy;
21544
21545 while (true)
21546 {
21547
21548 if ((end && row >= end) || !row->enabled_p)
21549 return NULL;
21550
21551
21552
21553 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21554 return NULL;
21555
21556
21557 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21558 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21559
21560
21561
21562
21563 && !row_for_charpos_p (row, charpos)))
21564 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21565 {
21566 struct glyph *g;
21567
21568 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21569 || (!best_row && !row->continued_p))
21570 return row;
21571
21572
21573
21574
21575 for (g = row->glyphs[TEXT_AREA];
21576 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21577 g++)
21578 {
21579 if (!STRINGP (g->object))
21580 {
21581 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21582 {
21583 mindif = eabs (g->charpos - charpos);
21584 best_row = row;
21585
21586 if (mindif == 0)
21587 return best_row;
21588 }
21589 }
21590 }
21591 }
21592 else if (best_row && !row->continued_p)
21593 return best_row;
21594 ++row;
21595 }
21596 }
21597
21598
21599
21600
21601
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611
21612
21613
21614
21615
21616
21617
21618
21619
21620
21621
21622
21623
21624
21625
21626
21627
21628
21629
21630
21631
21632
21633
21634
21635
21636
21637
21638
21639
21640
21641 static int
21642 try_window_id (struct window *w)
21643 {
21644 struct frame *f = XFRAME (w->frame);
21645 struct glyph_matrix *current_matrix = w->current_matrix;
21646 struct glyph_matrix *desired_matrix = w->desired_matrix;
21647 struct glyph_row *last_unchanged_at_beg_row;
21648 struct glyph_row *first_unchanged_at_end_row;
21649 struct glyph_row *row;
21650 struct glyph_row *bottom_row;
21651 int bottom_vpos;
21652 struct it it;
21653 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21654 int dvpos, dy;
21655 struct text_pos start_pos;
21656 struct run run;
21657 int first_unchanged_at_end_vpos = 0;
21658 struct glyph_row *last_text_row, *last_text_row_at_end;
21659 struct text_pos start;
21660 ptrdiff_t first_changed_charpos, last_changed_charpos;
21661
21662 #ifdef GLYPH_DEBUG
21663 if (inhibit_try_window_id)
21664 return 0;
21665 #endif
21666
21667
21668 #if false
21669 #define GIVE_UP(X) \
21670 do { \
21671 redisplay_trace ("try_window_id give up %d\n", X); \
21672 return 0; \
21673 } while (false)
21674 #else
21675 #define GIVE_UP(X) return 0
21676 #endif
21677
21678 SET_TEXT_POS_FROM_MARKER (start, w->start);
21679
21680
21681
21682 if (MINI_WINDOW_P (w))
21683 GIVE_UP (1);
21684
21685
21686 if (windows_or_buffers_changed || f->cursor_type_changed)
21687 GIVE_UP (2);
21688
21689
21690
21691
21692 if (w->last_overlay_modified != OVERLAY_MODIFF)
21693 GIVE_UP (200);
21694
21695
21696
21697
21698
21699 if (current_buffer->clip_changed
21700 || current_buffer->prevent_redisplay_optimizations_p)
21701 GIVE_UP (3);
21702
21703
21704 if (!FRAME_WINDOW_P (f)
21705 && (!FRAME_LINE_INS_DEL_OK (f)
21706 || !WINDOW_FULL_WIDTH_P (w)))
21707 GIVE_UP (4);
21708
21709
21710 if (PT < CHARPOS (start))
21711 GIVE_UP (5);
21712
21713
21714 if (w->last_modified == 0)
21715 GIVE_UP (6);
21716
21717
21718 if (w->hscroll != 0)
21719 GIVE_UP (7);
21720
21721
21722 if (!w->window_end_valid)
21723 GIVE_UP (8);
21724
21725
21726 if (!NILP (Vshow_trailing_whitespace))
21727 GIVE_UP (11);
21728
21729
21730
21731 if (overlay_arrows_changed_p (false))
21732 GIVE_UP (12);
21733
21734
21735
21736
21737
21738 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21739 GIVE_UP (21);
21740
21741
21742
21743
21744
21745
21746
21747
21748
21749 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21750 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21751 GIVE_UP (22);
21752
21753
21754
21755 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21756 GIVE_UP (23);
21757
21758
21759
21760 if (EQ (Vdisplay_line_numbers, Qrelative)
21761 || EQ (Vdisplay_line_numbers, Qvisual)
21762 || (!NILP (Vdisplay_line_numbers)
21763 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21764 Qline_number_current_line,
21765 w->frame))))
21766 GIVE_UP (24);
21767
21768
21769
21770
21771 if (composition_break_at_point)
21772 GIVE_UP (27);
21773
21774
21775
21776
21777
21778 if (MODIFF > SAVE_MODIFF
21779
21780 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21781 {
21782 if (GPT - BEG < BEG_UNCHANGED)
21783 BEG_UNCHANGED = GPT - BEG;
21784 if (Z - GPT < END_UNCHANGED)
21785 END_UNCHANGED = Z - GPT;
21786 }
21787
21788
21789 first_changed_charpos = BEG + BEG_UNCHANGED;
21790 last_changed_charpos = Z - END_UNCHANGED;
21791
21792
21793
21794
21795
21796
21797 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21798 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21799 && ((last_changed_charpos < CHARPOS (start)
21800 && CHARPOS (start) == BEGV)
21801 || (last_changed_charpos < CHARPOS (start) - 1
21802 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21803 {
21804 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21805 struct glyph_row *r0;
21806
21807
21808
21809 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21810 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21811 Z_delta = Z - Z_old;
21812 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21813
21814
21815
21816
21817 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21818 GIVE_UP (13);
21819
21820
21821
21822
21823 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21824 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21825 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21826
21827 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21828 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21829 {
21830
21831 if (Z_delta || Z_delta_bytes)
21832 {
21833 struct glyph_row *r1
21834 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21835 increment_matrix_positions (w->current_matrix,
21836 MATRIX_ROW_VPOS (r0, current_matrix),
21837 MATRIX_ROW_VPOS (r1, current_matrix),
21838 Z_delta, Z_delta_bytes);
21839 }
21840
21841
21842 row = row_containing_pos (w, PT, r0, NULL, 0);
21843 if (row)
21844 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21845 return 1;
21846 }
21847 }
21848
21849
21850
21851
21852
21853 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21854
21855
21856 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21857 || first_changed_charpos == last_changed_charpos))
21858 {
21859 struct glyph_row *r0;
21860
21861
21862
21863
21864 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21865 GIVE_UP (14);
21866
21867
21868
21869
21870 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21871 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21872
21873 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21874 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21875 {
21876
21877
21878 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21879 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
21880
21881
21882 row = row_containing_pos (w, PT, r0, NULL, 0);
21883 if (row)
21884 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21885 return 2;
21886 }
21887 }
21888
21889
21890
21891
21892
21893
21894
21895
21896 if (CHARPOS (start) >= first_changed_charpos
21897 && CHARPOS (start) <= last_changed_charpos)
21898 GIVE_UP (15);
21899
21900
21901
21902
21903
21904 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
21905 if (!TEXT_POS_EQUAL_P (start, row->minpos))
21906 GIVE_UP (16);
21907
21908
21909
21910 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
21911 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
21912 GIVE_UP (20);
21913
21914
21915
21916
21917
21918 #ifdef HAVE_NTGUI
21919 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
21920 GIVE_UP (25);
21921 #endif
21922
21923
21924
21925
21926
21927
21928
21929 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
21930 if (last_unchanged_at_beg_row)
21931 {
21932
21933
21934
21935
21936 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
21937 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
21938 && last_unchanged_at_beg_row > w->current_matrix->rows)
21939 --last_unchanged_at_beg_row;
21940
21941 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
21942 GIVE_UP (17);
21943
21944 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
21945 GIVE_UP (18);
21946
21947
21948
21949 if (it.sp > 1
21950 && it.method == GET_FROM_IMAGE && it.image_id == -1)
21951 GIVE_UP (26);
21952 start_pos = it.current.pos;
21953
21954
21955
21956
21957 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
21958 current_matrix);
21959 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
21960 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
21961
21962 eassert (it.hpos == 0 && it.current_x == 0);
21963 }
21964 else
21965 {
21966
21967
21968 start_display (&it, w, start);
21969 it.vpos = it.first_vpos;
21970 start_pos = it.current.pos;
21971 }
21972
21973
21974
21975
21976
21977
21978
21979 first_unchanged_at_end_row
21980 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
21981 IF_DEBUG (debug_delta = delta);
21982 IF_DEBUG (debug_delta_bytes = delta_bytes);
21983
21984
21985
21986
21987
21988
21989 stop_pos = 0;
21990 if (first_unchanged_at_end_row)
21991 {
21992 eassert (last_unchanged_at_beg_row == NULL
21993 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
21994
21995
21996
21997
21998
21999 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22000 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22001 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22002 < it.last_visible_y))
22003 ++first_unchanged_at_end_row;
22004
22005 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22006 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22007 >= it.last_visible_y))
22008 first_unchanged_at_end_row = NULL;
22009 else
22010 {
22011 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22012 + delta);
22013 first_unchanged_at_end_vpos
22014 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22015 eassert (stop_pos >= Z - END_UNCHANGED);
22016 }
22017 }
22018 else if (last_unchanged_at_beg_row == NULL)
22019 GIVE_UP (19);
22020
22021
22022 #ifdef GLYPH_DEBUG
22023
22024
22025
22026
22027 eassert (first_unchanged_at_end_row == NULL
22028 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22029
22030 debug_last_unchanged_at_beg_vpos
22031 = (last_unchanged_at_beg_row
22032 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22033 : -1);
22034 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22035
22036 #endif
22037
22038
22039
22040
22041
22042 w->cursor.vpos = -1;
22043 last_text_row = NULL;
22044 overlay_arrow_seen = false;
22045 if (it.current_y < it.last_visible_y
22046 && !f->fonts_changed
22047 && (first_unchanged_at_end_row == NULL
22048 || IT_CHARPOS (it) < stop_pos))
22049 it.glyph_row->reversed_p = false;
22050 while (it.current_y < it.last_visible_y
22051 && !f->fonts_changed
22052 && (first_unchanged_at_end_row == NULL
22053 || IT_CHARPOS (it) < stop_pos))
22054 {
22055 if (display_line (&it, -1))
22056 last_text_row = it.glyph_row - 1;
22057 }
22058
22059 if (f->fonts_changed)
22060 return -1;
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22071
22072 if (!w->window_end_valid)
22073 {
22074 clear_glyph_matrix (w->desired_matrix);
22075 return -1;
22076 }
22077
22078
22079
22080
22081 if (first_unchanged_at_end_row
22082
22083
22084 && it.current_y < it.last_visible_y)
22085 {
22086 dvpos = (it.vpos
22087 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22088 current_matrix));
22089 dy = it.current_y - first_unchanged_at_end_row->y;
22090 run.current_y = first_unchanged_at_end_row->y;
22091 run.desired_y = run.current_y + dy;
22092 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22093 }
22094 else
22095 {
22096 delta = delta_bytes = dvpos = dy
22097 = run.current_y = run.desired_y = run.height = 0;
22098 first_unchanged_at_end_row = NULL;
22099 }
22100 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111 if (w->cursor.vpos < 0)
22112 {
22113
22114 if (PT < CHARPOS (start_pos)
22115 && last_unchanged_at_beg_row)
22116 {
22117 row = row_containing_pos (w, PT,
22118 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22119 last_unchanged_at_beg_row + 1, 0);
22120 if (row)
22121 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22122 }
22123
22124
22125 else if (first_unchanged_at_end_row)
22126 {
22127 row = row_containing_pos (w, PT - delta,
22128 first_unchanged_at_end_row, NULL, 0);
22129 if (row)
22130 set_cursor_from_row (w, row, w->current_matrix, delta,
22131 delta_bytes, dy, dvpos);
22132 }
22133
22134
22135 if (w->cursor.vpos < 0)
22136 {
22137 clear_glyph_matrix (w->desired_matrix);
22138 return -1;
22139 }
22140 }
22141
22142
22143 {
22144 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22145 int bot_scroll_margin = top_scroll_margin;
22146 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22147
22148 if (window_wants_header_line (w))
22149 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22150 if (window_wants_tab_line (w))
22151 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22152
22153 if ((w->cursor.y < top_scroll_margin
22154 && CHARPOS (start) > BEGV)
22155
22156
22157 || (w->cursor.y
22158 + (cursor_row_fully_visible_p (w, false, true, true)
22159 ? 1
22160 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22161 {
22162 w->cursor.vpos = -1;
22163 clear_glyph_matrix (w->desired_matrix);
22164 return -1;
22165 }
22166 }
22167
22168
22169
22170
22171 if (dy && run.height)
22172 {
22173 update_begin (f);
22174
22175 if (FRAME_WINDOW_P (f))
22176 {
22177 #ifdef HAVE_WINDOW_SYSTEM
22178 gui_update_window_begin (w);
22179 FRAME_RIF (f)->clear_window_mouse_face (w);
22180 FRAME_RIF (f)->scroll_run_hook (w, &run);
22181 gui_update_window_end (w, false, false);
22182 #endif
22183 }
22184 else
22185 {
22186
22187
22188 int from_vpos
22189 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22190 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22191 int end = (WINDOW_TOP_EDGE_LINE (w)
22192 + window_wants_tab_line (w)
22193 + window_wants_header_line (w)
22194 + window_internal_height (w));
22195
22196 gui_clear_window_mouse_face (w);
22197
22198
22199 if (dvpos > 0)
22200 {
22201
22202
22203 set_terminal_window (f, end);
22204
22205
22206
22207 if (!FRAME_SCROLL_REGION_OK (f))
22208 ins_del_lines (f, end - dvpos, -dvpos);
22209
22210
22211
22212 ins_del_lines (f, from, dvpos);
22213 }
22214 else if (dvpos < 0)
22215 {
22216
22217
22218 set_terminal_window (f, end);
22219
22220
22221
22222
22223
22224 ins_del_lines (f, from + dvpos, dvpos);
22225
22226
22227
22228 if (!FRAME_SCROLL_REGION_OK (f))
22229 ins_del_lines (f, end + dvpos, -dvpos);
22230 }
22231
22232 set_terminal_window (f, 0);
22233 }
22234
22235 update_end (f);
22236 }
22237
22238
22239
22240
22241 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22242 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22243 if (dvpos < 0)
22244 {
22245 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22246 bottom_vpos, dvpos);
22247 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22248 bottom_vpos);
22249 }
22250 else if (dvpos > 0)
22251 {
22252 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22253 bottom_vpos, dvpos);
22254 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22255 first_unchanged_at_end_vpos + dvpos);
22256 }
22257
22258
22259
22260 if (!FRAME_WINDOW_P (f))
22261 sync_frame_with_window_matrix_rows (w);
22262
22263
22264 if (delta || delta_bytes)
22265 increment_matrix_positions (current_matrix,
22266 first_unchanged_at_end_vpos + dvpos,
22267 bottom_vpos, delta, delta_bytes);
22268
22269
22270 if (dy)
22271 shift_glyph_matrix (w, current_matrix,
22272 first_unchanged_at_end_vpos + dvpos,
22273 bottom_vpos, dy);
22274
22275 if (first_unchanged_at_end_row)
22276 {
22277 first_unchanged_at_end_row += dvpos;
22278 if (first_unchanged_at_end_row->y >= it.last_visible_y
22279 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22280 first_unchanged_at_end_row = NULL;
22281 }
22282
22283
22284
22285 last_text_row_at_end = NULL;
22286 if (dy < 0)
22287 {
22288
22289
22290
22291
22292
22293 int last_vpos = w->window_end_vpos + dvpos;
22294 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22295
22296
22297 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22298
22299
22300
22301
22302 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22303 {
22304 init_to_row_start (&it, w, last_row);
22305 it.vpos = last_vpos;
22306 it.current_y = last_row->y;
22307 }
22308 else
22309 {
22310 init_to_row_end (&it, w, last_row);
22311 it.vpos = 1 + last_vpos;
22312 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22313 ++last_row;
22314 }
22315
22316
22317
22318 it.continuation_lines_width = last_row->continuation_lines_width;
22319 it.hpos = it.current_x = 0;
22320
22321
22322 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22323 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22324 {
22325
22326
22327
22328
22329 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22330 if (display_line (&it, w->cursor.vpos))
22331 last_text_row_at_end = it.glyph_row - 1;
22332 }
22333 }
22334
22335
22336 if (first_unchanged_at_end_row && !last_text_row_at_end)
22337 {
22338
22339
22340
22341
22342 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22343 row = find_last_row_displaying_text (w->current_matrix, &it,
22344 first_unchanged_at_end_row);
22345 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22346 adjust_window_ends (w, row, true);
22347 eassert (w->window_end_bytepos >= 0);
22348 IF_DEBUG (debug_method_add (w, "A"));
22349 }
22350 else if (last_text_row_at_end)
22351 {
22352 adjust_window_ends (w, last_text_row_at_end, false);
22353 eassert (w->window_end_bytepos >= 0);
22354 IF_DEBUG (debug_method_add (w, "B"));
22355 }
22356 else if (last_text_row)
22357 {
22358
22359
22360
22361 adjust_window_ends (w, last_text_row, false);
22362 eassert (w->window_end_bytepos >= 0);
22363 }
22364 else if (first_unchanged_at_end_row == NULL
22365 && last_text_row == NULL
22366 && last_text_row_at_end == NULL)
22367 {
22368
22369
22370 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22371 int vpos = w->window_end_vpos;
22372 struct glyph_row *current_row = current_matrix->rows + vpos;
22373 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22374
22375 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22376 {
22377 eassert (first_vpos <= vpos);
22378 if (desired_row->enabled_p)
22379 {
22380 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22381 row = desired_row;
22382 }
22383 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22384 row = current_row;
22385 }
22386
22387 w->window_end_vpos = vpos + 1;
22388 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22389 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22390 eassert (w->window_end_bytepos >= 0);
22391 IF_DEBUG (debug_method_add (w, "C"));
22392 }
22393 else
22394 emacs_abort ();
22395
22396 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22397 debug_end_vpos = w->window_end_vpos));
22398
22399
22400 w->window_end_valid = false;
22401 w->desired_matrix->no_scrolling_p = true;
22402 return 3;
22403
22404 #undef GIVE_UP
22405 }
22406
22407
22408
22409
22410
22411
22412
22413 #ifdef GLYPH_DEBUG
22414
22415 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22416 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22417 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22418
22419
22420
22421
22422
22423
22424
22425
22426 void
22427 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22428 {
22429 int i;
22430 for (i = 0; i < matrix->nrows; ++i)
22431 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22432 }
22433
22434
22435
22436
22437
22438 void
22439 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22440 {
22441 if (glyph->type == CHAR_GLYPH
22442 || glyph->type == GLYPHLESS_GLYPH)
22443 {
22444 fprintf (stderr,
22445 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22446 glyph - row->glyphs[TEXT_AREA],
22447 (glyph->type == CHAR_GLYPH
22448 ? 'C'
22449 : 'G'),
22450 glyph->charpos,
22451 (BUFFERP (glyph->object)
22452 ? 'B'
22453 : (STRINGP (glyph->object)
22454 ? 'S'
22455 : (NILP (glyph->object)
22456 ? '0'
22457 : '-'))),
22458 glyph->pixel_width,
22459 glyph->u.ch,
22460 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22461 ? (int) glyph->u.ch
22462 : '.'),
22463 glyph->face_id,
22464 glyph->left_box_line_p,
22465 glyph->right_box_line_p);
22466 }
22467 else if (glyph->type == STRETCH_GLYPH)
22468 {
22469 fprintf (stderr,
22470 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22471 glyph - row->glyphs[TEXT_AREA],
22472 'S',
22473 glyph->charpos,
22474 (BUFFERP (glyph->object)
22475 ? 'B'
22476 : (STRINGP (glyph->object)
22477 ? 'S'
22478 : (NILP (glyph->object)
22479 ? '0'
22480 : '-'))),
22481 glyph->pixel_width,
22482 0u,
22483 ' ',
22484 glyph->face_id,
22485 glyph->left_box_line_p,
22486 glyph->right_box_line_p);
22487 }
22488 else if (glyph->type == IMAGE_GLYPH)
22489 {
22490 fprintf (stderr,
22491 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22492 glyph - row->glyphs[TEXT_AREA],
22493 'I',
22494 glyph->charpos,
22495 (BUFFERP (glyph->object)
22496 ? 'B'
22497 : (STRINGP (glyph->object)
22498 ? 'S'
22499 : (NILP (glyph->object)
22500 ? '0'
22501 : '-'))),
22502 glyph->pixel_width,
22503 (unsigned int) glyph->u.img_id,
22504 '.',
22505 glyph->face_id,
22506 glyph->left_box_line_p,
22507 glyph->right_box_line_p);
22508 }
22509 else if (glyph->type == COMPOSITE_GLYPH)
22510 {
22511 fprintf (stderr,
22512 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22513 glyph - row->glyphs[TEXT_AREA],
22514 '+',
22515 glyph->charpos,
22516 (BUFFERP (glyph->object)
22517 ? 'B'
22518 : (STRINGP (glyph->object)
22519 ? 'S'
22520 : (NILP (glyph->object)
22521 ? '0'
22522 : '-'))),
22523 glyph->pixel_width,
22524 (unsigned int) glyph->u.cmp.id);
22525 if (glyph->u.cmp.automatic)
22526 fprintf (stderr,
22527 "[%d-%d]",
22528 glyph->slice.cmp.from, glyph->slice.cmp.to);
22529 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22530 glyph->face_id,
22531 glyph->left_box_line_p,
22532 glyph->right_box_line_p);
22533 }
22534 else if (glyph->type == XWIDGET_GLYPH)
22535 {
22536 #ifndef HAVE_XWIDGETS
22537 eassume (false);
22538 #else
22539 fprintf (stderr,
22540 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22541 glyph - row->glyphs[TEXT_AREA],
22542 'X',
22543 glyph->charpos,
22544 (BUFFERP (glyph->object)
22545 ? 'B'
22546 : (STRINGP (glyph->object)
22547 ? 'S'
22548 : '-')),
22549 glyph->pixel_width,
22550 glyph->u.xwidget,
22551 '.',
22552 glyph->face_id,
22553 glyph->left_box_line_p,
22554 glyph->right_box_line_p);
22555 #endif
22556 }
22557 }
22558
22559
22560
22561
22562
22563
22564
22565 void
22566 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22567 {
22568 if (glyphs != 1)
22569 {
22570 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22571 "==============================================================================\n"),
22572 stderr);
22573 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22574 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22575 vpos,
22576 MATRIX_ROW_START_CHARPOS (row),
22577 MATRIX_ROW_END_CHARPOS (row),
22578 row->used[TEXT_AREA],
22579 row->contains_overlapping_glyphs_p,
22580 row->enabled_p,
22581 row->truncated_on_left_p,
22582 row->truncated_on_right_p,
22583 row->continued_p,
22584 MATRIX_ROW_CONTINUATION_LINE_P (row),
22585 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22586 row->ends_at_zv_p,
22587 row->fill_line_p,
22588 row->ends_in_middle_of_char_p,
22589 row->starts_in_middle_of_char_p,
22590 row->mouse_face_p,
22591 row->x,
22592 row->y,
22593 row->pixel_width,
22594 row->height,
22595 row->visible_height,
22596 row->ascent,
22597 row->phys_ascent);
22598
22599 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22600 row->end.overlay_string_index,
22601 row->continuation_lines_width);
22602 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22603 CHARPOS (row->start.string_pos),
22604 CHARPOS (row->end.string_pos));
22605 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22606 row->end.dpvec_index);
22607 }
22608
22609 if (glyphs > 1)
22610 {
22611 int area;
22612
22613 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22614 {
22615 struct glyph *glyph = row->glyphs[area];
22616 struct glyph *glyph_end = glyph + row->used[area];
22617
22618
22619 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22620 ++glyph_end;
22621
22622 if (glyph < glyph_end)
22623 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22624 stderr);
22625
22626 for (; glyph < glyph_end; ++glyph)
22627 dump_glyph (row, glyph, area);
22628 }
22629 }
22630 else if (glyphs == 1)
22631 {
22632 int area;
22633 char s[SHRT_MAX + 4];
22634
22635 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22636 {
22637 int i;
22638
22639 for (i = 0; i < row->used[area]; ++i)
22640 {
22641 struct glyph *glyph = row->glyphs[area] + i;
22642 if (i == row->used[area] - 1
22643 && area == TEXT_AREA
22644 && NILP (glyph->object)
22645 && glyph->type == CHAR_GLYPH
22646 && glyph->u.ch == ' ')
22647 {
22648 strcpy (&s[i], "[\\n]");
22649 i += 4;
22650 }
22651 else if (glyph->type == CHAR_GLYPH
22652 && glyph->u.ch < 0x80
22653 && glyph->u.ch >= ' ')
22654 s[i] = glyph->u.ch;
22655 else
22656 s[i] = '.';
22657 }
22658
22659 s[i] = '\0';
22660 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22661 }
22662 }
22663 }
22664
22665
22666 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22667 Sdump_glyph_matrix, 0, 1, "p",
22668 doc:
22669
22670
22671
22672
22673
22674 )
22675 (Lisp_Object glyphs)
22676 {
22677 struct window *w = XWINDOW (selected_window);
22678 struct buffer *buffer = XBUFFER (w->contents);
22679
22680 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22681 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22682 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22683 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22684 fputs ("=============================================\n", stderr);
22685 dump_glyph_matrix (w->current_matrix,
22686 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22687 return Qnil;
22688 }
22689
22690
22691 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22692 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22693 )
22694 (void)
22695 {
22696 struct frame *f = XFRAME (selected_frame);
22697
22698 if (f->current_matrix)
22699 dump_glyph_matrix (f->current_matrix, 1);
22700 else
22701 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22702 return Qnil;
22703 }
22704
22705
22706 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22707 doc:
22708
22709
22710
22711
22712 )
22713 (Lisp_Object row, Lisp_Object glyphs)
22714 {
22715 struct glyph_matrix *matrix;
22716 EMACS_INT vpos;
22717
22718 if (NILP (row))
22719 {
22720 int d1, d2, d3, d4, d5, ypos;
22721 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22722 &d1, &d2, &d3, &d4, &d5, &ypos);
22723 if (visible_p)
22724 vpos = ypos;
22725 else
22726 vpos = 0;
22727 }
22728 else
22729 {
22730 CHECK_FIXNUM (row);
22731 vpos = XFIXNUM (row);
22732 }
22733 matrix = XWINDOW (selected_window)->current_matrix;
22734 if (vpos >= 0 && vpos < matrix->nrows)
22735 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22736 vpos,
22737 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22738 return Qnil;
22739 }
22740
22741
22742 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22743 doc:
22744
22745
22746
22747
22748
22749
22750 )
22751 (Lisp_Object row, Lisp_Object glyphs)
22752 {
22753 #if defined (HAVE_WINDOW_SYSTEM)
22754 struct frame *sf = SELECTED_FRAME ();
22755 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22756 ? XWINDOW (sf->tab_bar_window)->current_matrix
22757 : sf->current_matrix;
22758 EMACS_INT vpos;
22759
22760 if (NILP (row))
22761 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22762 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22763 else
22764 {
22765 CHECK_FIXNUM (row);
22766 vpos = XFIXNUM (row);
22767 }
22768 if (vpos >= 0 && vpos < m->nrows)
22769 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22770 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22771 #endif
22772 return Qnil;
22773 }
22774
22775 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22776 doc:
22777
22778
22779
22780
22781
22782
22783 )
22784 (Lisp_Object row, Lisp_Object glyphs)
22785 {
22786 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22787 struct frame *sf = SELECTED_FRAME ();
22788 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22789 EMACS_INT vpos;
22790
22791 if (NILP (row))
22792 vpos = 0;
22793 else
22794 {
22795 CHECK_FIXNUM (row);
22796 vpos = XFIXNUM (row);
22797 }
22798 if (vpos >= 0 && vpos < m->nrows)
22799 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22800 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22801 #endif
22802 return Qnil;
22803 }
22804
22805
22806 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22807 doc:
22808 )
22809 (Lisp_Object arg)
22810 {
22811 if (NILP (arg))
22812 trace_redisplay_p = !trace_redisplay_p;
22813 else
22814 {
22815 arg = Fprefix_numeric_value (arg);
22816 trace_redisplay_p = XFIXNUM (arg) > 0;
22817 }
22818
22819 return Qnil;
22820 }
22821
22822
22823 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22824 doc:
22825 )
22826 (ptrdiff_t nargs, Lisp_Object *args)
22827 {
22828 Lisp_Object s = Fformat (nargs, args);
22829 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22830 return Qnil;
22831 }
22832
22833 #endif
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845 static struct glyph_row *
22846 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22847 {
22848 struct frame *f = XFRAME (WINDOW_FRAME (w));
22849 struct buffer *buffer = XBUFFER (w->contents);
22850 struct buffer *old = current_buffer;
22851 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22852 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22853 const unsigned char *arrow_end = arrow_string + arrow_len;
22854 const unsigned char *p;
22855 struct it it;
22856 bool multibyte_p;
22857 int n_glyphs_before;
22858
22859 set_buffer_temp (buffer);
22860 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22861 scratch_glyph_row.reversed_p = false;
22862 it.glyph_row->used[TEXT_AREA] = 0;
22863 SET_TEXT_POS (it.position, 0, 0);
22864
22865 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22866 p = arrow_string;
22867 while (p < arrow_end)
22868 {
22869 Lisp_Object face, ilisp;
22870
22871
22872 if (multibyte_p)
22873 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22874 else
22875 {
22876 it.c = it.char_to_display = *p, it.len = 1;
22877 if (! ASCII_CHAR_P (it.c))
22878 it.char_to_display = BYTE8_TO_CHAR (it.c);
22879 }
22880 p += it.len;
22881
22882
22883 ilisp = make_fixnum (char_num++);
22884 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
22885 it.face_id = compute_char_face (f, it.char_to_display, face);
22886
22887
22888 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
22889 SET_TEXT_POS (it.position, -1, -1);
22890 PRODUCE_GLYPHS (&it);
22891
22892
22893
22894 if (it.current_x > it.last_visible_x)
22895 {
22896 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
22897 break;
22898 }
22899 }
22900
22901 set_buffer_temp (old);
22902 return it.glyph_row;
22903 }
22904
22905
22906
22907
22908
22909 static void
22910 insert_left_trunc_glyphs (struct it *it)
22911 {
22912 struct it truncate_it;
22913 struct glyph *from, *end, *to, *toend;
22914
22915 eassert (!FRAME_WINDOW_P (it->f)
22916 || (!it->glyph_row->reversed_p
22917 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
22918 || (it->glyph_row->reversed_p
22919 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
22920
22921
22922 truncate_it = *it;
22923 truncate_it.current_x = 0;
22924 truncate_it.face_id = DEFAULT_FACE_ID;
22925 truncate_it.glyph_row = &scratch_glyph_row;
22926 truncate_it.area = TEXT_AREA;
22927 truncate_it.glyph_row->used[TEXT_AREA] = 0;
22928 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
22929 truncate_it.object = Qnil;
22930 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
22931
22932
22933 if (!it->glyph_row->reversed_p)
22934 {
22935 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22936
22937 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22938 end = from + tused;
22939 to = it->glyph_row->glyphs[TEXT_AREA];
22940 toend = to + it->glyph_row->used[TEXT_AREA];
22941 if (FRAME_WINDOW_P (it->f))
22942 {
22943
22944
22945
22946
22947
22948
22949
22950 int w = 0;
22951 struct glyph *g = to;
22952 short used;
22953
22954
22955
22956
22957
22958
22959 it->glyph_row->x = 0;
22960 while (g < toend && w < it->truncation_pixel_width)
22961 {
22962 w += g->pixel_width;
22963 ++g;
22964 }
22965 if (g - to - tused > 0)
22966 {
22967 memmove (to + tused, g, (toend - g) * sizeof(*g));
22968 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
22969 }
22970 used = it->glyph_row->used[TEXT_AREA];
22971 if (it->glyph_row->truncated_on_right_p
22972 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
22973 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
22974 == STRETCH_GLYPH)
22975 {
22976 int extra = w - it->truncation_pixel_width;
22977
22978 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
22979 }
22980 }
22981
22982 while (from < end)
22983 *to++ = *from++;
22984
22985
22986 if (!FRAME_WINDOW_P (it->f))
22987 {
22988 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
22989 {
22990 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22991 while (from < end)
22992 *to++ = *from++;
22993 }
22994 }
22995
22996 if (to > toend)
22997 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
22998 }
22999 else
23000 {
23001 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23002
23003
23004
23005 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23006 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23007 toend = it->glyph_row->glyphs[TEXT_AREA];
23008 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23009 if (FRAME_WINDOW_P (it->f))
23010 {
23011 int w = 0;
23012 struct glyph *g = to;
23013
23014 while (g >= toend && w < it->truncation_pixel_width)
23015 {
23016 w += g->pixel_width;
23017 --g;
23018 }
23019 if (to - g - tused > 0)
23020 to = g + tused;
23021 if (it->glyph_row->truncated_on_right_p
23022 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23023 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23024 {
23025 int extra = w - it->truncation_pixel_width;
23026
23027 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23028 }
23029 }
23030
23031 while (from >= end && to >= toend)
23032 *to-- = *from--;
23033 if (!FRAME_WINDOW_P (it->f))
23034 {
23035 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23036 {
23037 from =
23038 truncate_it.glyph_row->glyphs[TEXT_AREA]
23039 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23040 while (from >= end && to >= toend)
23041 *to-- = *from--;
23042 }
23043 }
23044 if (from >= end)
23045 {
23046
23047
23048 int move_by = from - end + 1;
23049 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23050 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23051
23052 for ( ; g >= g0; g--)
23053 g[move_by] = *g;
23054 while (from >= end)
23055 *to-- = *from--;
23056 it->glyph_row->used[TEXT_AREA] += move_by;
23057 }
23058 }
23059 }
23060
23061
23062 unsigned
23063 row_hash (struct glyph_row *row)
23064 {
23065 int area, k;
23066 unsigned hashval = 0;
23067
23068 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23069 for (k = 0; k < row->used[area]; ++k)
23070 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23071 + row->glyphs[area][k].u.val
23072 + row->glyphs[area][k].face_id
23073 + row->glyphs[area][k].padding_p
23074 + (row->glyphs[area][k].type << 2));
23075
23076 return hashval;
23077 }
23078
23079
23080
23081
23082
23083
23084
23085
23086
23087
23088
23089
23090
23091
23092
23093
23094
23095
23096 static void
23097 compute_line_metrics (struct it *it)
23098 {
23099 struct glyph_row *row = it->glyph_row;
23100
23101 if (FRAME_WINDOW_P (it->f))
23102 {
23103 int i, min_y, max_y;
23104
23105
23106
23107
23108 if (row->height == 0)
23109 {
23110 if (it->max_ascent + it->max_descent == 0)
23111 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23112 row->ascent = it->max_ascent;
23113 row->height = it->max_ascent + it->max_descent;
23114 row->phys_ascent = it->max_phys_ascent;
23115 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23116 row->extra_line_spacing = it->max_extra_line_spacing;
23117 }
23118
23119
23120 row->pixel_width = row->x;
23121 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23122 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23123
23124 eassert (row->pixel_width >= 0);
23125 eassert (row->ascent >= 0 && row->height > 0);
23126
23127 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23128 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23129
23130
23131
23132
23133 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23134 && row->phys_ascent > row->ascent)
23135 {
23136 row->height += row->phys_ascent - row->ascent;
23137 row->ascent = row->phys_ascent;
23138 }
23139
23140
23141 row->visible_height = row->height;
23142
23143 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23144 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23145
23146 if (row->y < min_y)
23147 row->visible_height -= min_y - row->y;
23148 if (row->y + row->height > max_y)
23149 row->visible_height -= row->y + row->height - max_y;
23150 }
23151 else
23152 {
23153 row->pixel_width = row->used[TEXT_AREA];
23154 if (row->continued_p)
23155 row->pixel_width -= it->continuation_pixel_width;
23156 else if (row->truncated_on_right_p)
23157 row->pixel_width -= it->truncation_pixel_width;
23158 row->ascent = row->phys_ascent = 0;
23159 row->height = row->phys_height = row->visible_height = 1;
23160 row->extra_line_spacing = 0;
23161 }
23162
23163
23164 row->hash = row_hash (row);
23165
23166 it->max_ascent = it->max_descent = 0;
23167 it->max_phys_ascent = it->max_phys_descent = 0;
23168 }
23169
23170
23171 static void
23172 clear_position (struct it *it)
23173 {
23174 it->position.charpos = 0;
23175 it->position.bytepos = 0;
23176 }
23177
23178
23179
23180
23181
23182
23183
23184
23185
23186
23187
23188
23189
23190 static bool
23191 append_space_for_newline (struct it *it, bool default_face_p)
23192 {
23193 int n = it->glyph_row->used[TEXT_AREA];
23194
23195 if (it->glyph_row->glyphs[TEXT_AREA] + n
23196 < it->glyph_row->glyphs[1 + TEXT_AREA])
23197 {
23198
23199
23200
23201
23202 enum display_element_type saved_what = it->what;
23203 int saved_c = it->c, saved_len = it->len;
23204 int saved_char_to_display = it->char_to_display;
23205 int saved_x = it->current_x;
23206 const int saved_face_id = it->face_id;
23207 bool saved_box_end = it->end_of_box_run_p;
23208 struct text_pos saved_pos = it->position;
23209 Lisp_Object saved_object = it->object;
23210 struct face *face;
23211
23212 it->what = IT_CHARACTER;
23213 clear_position (it);
23214 it->object = Qnil;
23215 it->len = 1;
23216
23217 int char_width = 1;
23218
23219 if (default_face_p
23220 #ifdef HAVE_WINDOW_SYSTEM
23221 || FRAME_WINDOW_P (it->f)
23222 #endif
23223 )
23224 {
23225 const int local_default_face_id =
23226 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23227
23228 #ifdef HAVE_WINDOW_SYSTEM
23229 if (FRAME_WINDOW_P (it->f))
23230 {
23231 struct face *default_face
23232 = FACE_FROM_ID (it->f, local_default_face_id);
23233 struct font *font = (default_face->font
23234 ? default_face->font
23235 : FRAME_FONT (it->f));
23236 char_width = (font->average_width
23237 ? font->average_width
23238 : font->space_width);
23239 }
23240 #endif
23241 if (default_face_p)
23242 it->face_id = local_default_face_id;
23243 }
23244
23245
23246
23247
23248 const int indicator_column =
23249 fill_column_indicator_column (it, char_width);
23250 int saved_end_of_box_run = it->end_of_box_run_p;
23251 bool should_keep_end_of_box_run = false;
23252
23253 if (it->current_x == indicator_column)
23254 {
23255 it->c = it->char_to_display
23256 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23257 it->face_id
23258 = merge_faces (it->w, Qfill_column_indicator,
23259 0, saved_face_id);
23260 face = FACE_FROM_ID (it->f, it->face_id);
23261 }
23262 else
23263 {
23264 it->c = it->char_to_display = ' ';
23265
23266
23267
23268 face = FACE_FROM_ID (it->f, it->face_id);
23269 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23270
23271
23272
23273
23274 if (!(it->glyph_row->reversed_p
23275
23276
23277
23278 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23279 should_keep_end_of_box_run = true;
23280 }
23281 PRODUCE_GLYPHS (it);
23282
23283
23284 if (should_keep_end_of_box_run)
23285 it->end_of_box_run_p = saved_end_of_box_run;
23286 #ifdef HAVE_WINDOW_SYSTEM
23287 if (FRAME_WINDOW_P (it->f))
23288 {
23289
23290
23291
23292 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23293 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23294 if (n == 0)
23295 {
23296 Lisp_Object height, total_height;
23297 int extra_line_spacing = it->extra_line_spacing;
23298 int boff = font->baseline_offset;
23299
23300 if (font->vertical_centering)
23301 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23302
23303 it->object = saved_object;
23304 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23305
23306
23307 height = get_it_property (it, Qline_height);
23308 if (CONSP (height)
23309 && CONSP (XCDR (height))
23310 && NILP (XCDR (XCDR (height))))
23311 {
23312 total_height = XCAR (XCDR (height));
23313 height = XCAR (height);
23314 }
23315 else
23316 total_height = Qnil;
23317 height = calc_line_height_property (it, height, font, boff, true);
23318
23319 if (it->override_ascent >= 0)
23320 {
23321 it->ascent = it->override_ascent;
23322 it->descent = it->override_descent;
23323 boff = it->override_boff;
23324 }
23325 if (EQ (height, Qt))
23326 extra_line_spacing = 0;
23327 else
23328 {
23329 Lisp_Object spacing;
23330
23331 it->phys_ascent = it->ascent;
23332 it->phys_descent = it->descent;
23333 if (!NILP (height)
23334 && XFIXNUM (height) > it->ascent + it->descent)
23335 it->ascent = XFIXNUM (height) - it->descent;
23336
23337 if (!NILP (total_height))
23338 spacing = calc_line_height_property (it, total_height, font,
23339 boff, false);
23340 else
23341 {
23342 spacing = get_it_property (it, Qline_spacing);
23343 spacing = calc_line_height_property (it, spacing, font,
23344 boff, false);
23345 }
23346 if (FIXNUMP (spacing))
23347 {
23348 extra_line_spacing = XFIXNUM (spacing);
23349 if (!NILP (total_height))
23350 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23351 }
23352 }
23353 if (extra_line_spacing > 0)
23354 {
23355 it->descent += extra_line_spacing;
23356 if (extra_line_spacing > it->max_extra_line_spacing)
23357 it->max_extra_line_spacing = extra_line_spacing;
23358 }
23359 it->max_ascent = it->ascent;
23360 it->max_descent = it->descent;
23361
23362 it->glyph_row->height = 0;
23363 }
23364
23365 g->ascent = it->max_ascent;
23366 g->descent = it->max_descent;
23367 }
23368 #endif
23369 it->override_ascent = -1;
23370 it->constrain_row_ascent_descent_p = false;
23371 it->current_x = saved_x;
23372 it->object = saved_object;
23373 it->position = saved_pos;
23374 it->what = saved_what;
23375 it->face_id = saved_face_id;
23376 it->len = saved_len;
23377 it->c = saved_c;
23378 it->char_to_display = saved_char_to_display;
23379 it->end_of_box_run_p = saved_box_end;
23380 return true;
23381 }
23382
23383 return false;
23384 }
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394 static void
23395 extend_face_to_end_of_line (struct it *it)
23396 {
23397 struct frame *f = it->f;
23398
23399
23400
23401
23402
23403
23404 if ((it->current_x >= it->last_visible_x
23405 + (!FRAME_WINDOW_P (f)
23406 && it->glyph_row->reversed_p
23407 && !it->glyph_row->continued_p))
23408
23409
23410 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23411 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23412 return;
23413
23414 specpdl_ref count = SPECPDL_INDEX ();
23415
23416
23417
23418
23419 specbind (Qinhibit_quit, Qt);
23420
23421 struct face *default_face =
23422 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23423 if (!default_face)
23424 return;
23425
23426 const int extend_face_id =
23427 (it->face_id == default_face->id || it->s != NULL)
23428 ? it->face_id
23429 : (it->glyph_row->ends_at_zv_p
23430 ? default_face->id
23431 : face_at_pos (it, LFACE_EXTEND_INDEX));
23432 unbind_to (count, Qnil);
23433
23434
23435
23436
23437 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23438 ? it->saved_face_id
23439 : extend_face_id));
23440
23441 if (FRAME_WINDOW_P (f)
23442 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23443 && face->box == FACE_NO_BOX
23444 && face->underline == FACE_NO_UNDERLINE
23445 && !face->overline_p
23446 && !face->strike_through_p
23447 && face->background == FRAME_BACKGROUND_PIXEL (f)
23448 #ifdef HAVE_WINDOW_SYSTEM
23449 && !face->stipple
23450 #endif
23451 && !it->glyph_row->reversed_p
23452 && !display_fill_column_indicator)
23453 return;
23454
23455
23456
23457 it->glyph_row->fill_line_p = true;
23458
23459 const int orig_face_id = it->face_id;
23460
23461
23462
23463
23464
23465 if (!ASCII_CHAR_P (it->c))
23466 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23467
23468
23469 #ifdef HAVE_WINDOW_SYSTEM
23470 if (FRAME_WINDOW_P (f))
23471 {
23472
23473
23474 if (it->glyph_row->used[TEXT_AREA] == 0)
23475 {
23476 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23477 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23478 it->glyph_row->used[TEXT_AREA] = 1;
23479 }
23480
23481
23482 if (!(it->glyph_row->mode_line_p
23483 || (WINDOWP (f->tab_bar_window)
23484 && it->w == XWINDOW (f->tab_bar_window))
23485 #ifndef HAVE_EXT_TOOL_BAR
23486 || (WINDOWP (f->tool_bar_window)
23487 && it->w == XWINDOW (f->tool_bar_window))
23488 #endif
23489 ))
23490 {
23491 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23492 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23493 {
23494 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23495 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23496 default_face->id;
23497 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23498 }
23499 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23500 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23501 {
23502 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23503 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23504 default_face->id;
23505 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23506 }
23507
23508 struct font *font = (default_face->font
23509 ? default_face->font
23510 : FRAME_FONT (f));
23511
23512 const int char_width = (font->average_width
23513 ? font->average_width
23514 : font->space_width);
23515
23516 const int indicator_column =
23517 fill_column_indicator_column (it, char_width);
23518
23519 const char saved_char = it->char_to_display;
23520 const struct text_pos saved_pos = it->position;
23521 const bool saved_avoid_cursor = it->avoid_cursor_p;
23522 const bool saved_box_start = it->start_of_box_run_p;
23523 Lisp_Object save_object = it->object;
23524 const int saved_face_id = it->face_id;
23525
23526 it->face_id = extend_face_id;
23527 it->avoid_cursor_p = true;
23528 it->object = Qnil;
23529
23530 const int stretch_height = it->ascent + it->descent;
23531 const int stretch_ascent =
23532 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23533
23534 if (indicator_column >= 0
23535 && indicator_column > it->current_x
23536 && indicator_column < it->last_visible_x)
23537 {
23538
23539
23540
23541
23542 const int stretch_width =
23543 indicator_column - it->current_x - char_width;
23544
23545 clear_position (it);
23546
23547
23548
23549 if (stretch_width > 0)
23550 {
23551 append_stretch_glyph (it, Qnil, stretch_width,
23552 stretch_height, stretch_ascent);
23553 }
23554
23555
23556
23557 if (it->current_x < indicator_column)
23558 {
23559 const int save_face_id = it->face_id;
23560 const int save_ascent = it->ascent;
23561 const int save_descent = it->descent;
23562 it->char_to_display
23563 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23564 it->face_id
23565 = merge_faces (it->w, Qfill_column_indicator,
23566 0, extend_face_id);
23567 PRODUCE_GLYPHS (it);
23568 it->face_id = save_face_id;
23569 it->ascent = save_ascent;
23570 it->descent = save_descent;
23571 }
23572 }
23573
23574
23575
23576 if (!it->glyph_row->reversed_p)
23577 {
23578 const int stretch_width = it->last_visible_x - it->current_x;
23579
23580 if (stretch_width > 0)
23581 {
23582 clear_position (it);
23583 append_stretch_glyph (it, Qnil, stretch_width,
23584 stretch_height, stretch_ascent);
23585 }
23586 }
23587
23588 it->char_to_display = saved_char;
23589 it->position = saved_pos;
23590 it->avoid_cursor_p = saved_avoid_cursor;
23591 it->start_of_box_run_p = saved_box_start;
23592 it->object = save_object;
23593 it->face_id = saved_face_id;
23594 }
23595 if (it->glyph_row->reversed_p)
23596 {
23597
23598
23599
23600
23601
23602 struct font *font = face->font ? face->font : FRAME_FONT (f);
23603 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23604 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23605 struct glyph *g;
23606 int row_width, stretch_ascent, stretch_width;
23607 struct text_pos saved_pos;
23608 int saved_face_id;
23609 bool saved_avoid_cursor, saved_box_start;
23610
23611 for (row_width = 0, g = row_start; g < row_end; g++)
23612 row_width += g->pixel_width;
23613
23614
23615
23616
23617 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23618 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23619 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23620 stretch_width = window_box_width (it->w, TEXT_AREA);
23621 else
23622 stretch_width = it->last_visible_x - it->first_visible_x;
23623 stretch_width -= row_width;
23624
23625 if (stretch_width > 0)
23626 {
23627 stretch_ascent =
23628 (((it->ascent + it->descent)
23629 * FONT_BASE (font)) / FONT_HEIGHT (font));
23630 saved_pos = it->position;
23631 clear_position (it);
23632 saved_avoid_cursor = it->avoid_cursor_p;
23633 it->avoid_cursor_p = true;
23634 saved_face_id = it->face_id;
23635 saved_box_start = it->start_of_box_run_p;
23636
23637
23638
23639 it->face_id = (it->glyph_row->ends_at_zv_p ?
23640 default_face->id : face->id);
23641
23642 it->start_of_box_run_p = false;
23643 append_stretch_glyph (it, Qnil, stretch_width,
23644 it->ascent + it->descent, stretch_ascent);
23645 it->position = saved_pos;
23646 it->avoid_cursor_p = saved_avoid_cursor;
23647 it->face_id = saved_face_id;
23648 it->start_of_box_run_p = saved_box_start;
23649 }
23650
23651
23652
23653
23654 if (stretch_width < 0)
23655 it->glyph_row->x = stretch_width;
23656 }
23657 it->face_id = orig_face_id;
23658 }
23659 else
23660 #endif
23661 {
23662
23663 int saved_x = it->current_x;
23664 struct text_pos saved_pos = it->position;
23665 Lisp_Object saved_object = it->object;;
23666 enum display_element_type saved_what = it->what;
23667
23668 it->what = IT_CHARACTER;
23669 clear_position (it);
23670 it->object = Qnil;
23671 it->c = it->char_to_display = ' ';
23672 it->len = 1;
23673
23674 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23675 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23676 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23677 && !it->glyph_row->mode_line_p
23678 && face->background != FRAME_BACKGROUND_PIXEL (f))
23679 {
23680 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23681 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23682
23683 for (it->current_x = 0; g < e; g++)
23684 it->current_x += g->pixel_width;
23685
23686 it->area = LEFT_MARGIN_AREA;
23687 it->face_id = default_face->id;
23688 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23689 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23690 && g < it->glyph_row->glyphs[TEXT_AREA])
23691 {
23692 PRODUCE_GLYPHS (it);
23693
23694
23695 it->current_x += it->pixel_width;
23696 g++;
23697 }
23698
23699 it->current_x = saved_x;
23700 it->area = TEXT_AREA;
23701 }
23702
23703
23704
23705
23706 it->face_id = (it->glyph_row->ends_at_zv_p ?
23707 default_face->id : face->id);
23708
23709
23710
23711
23712
23713 it->current_x = it->glyph_row->used[TEXT_AREA];
23714
23715
23716
23717
23718
23719
23720
23721
23722 const int indicator_column =
23723 fill_column_indicator_column (it, 1) - it->first_visible_x;
23724
23725
23726 while (it->current_x <= it->last_visible_x)
23727 {
23728 if (it->current_x != indicator_column)
23729 PRODUCE_GLYPHS (it);
23730 else
23731 {
23732 int saved_face_id = it->face_id;
23733 it->face_id
23734 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23735 it->c = it->char_to_display
23736 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23737
23738 PRODUCE_GLYPHS (it);
23739
23740 it->face_id = saved_face_id;
23741 it->c = it->char_to_display = ' ';
23742 }
23743 }
23744
23745 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23746 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23747 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23748 && !it->glyph_row->mode_line_p
23749 && face->background != FRAME_BACKGROUND_PIXEL (f))
23750 {
23751 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23752 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23753
23754 for ( ; g < e; g++)
23755 it->current_x += g->pixel_width;
23756
23757 it->area = RIGHT_MARGIN_AREA;
23758 it->face_id = default_face->id;
23759 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23760 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23761 && g < it->glyph_row->glyphs[LAST_AREA])
23762 {
23763 PRODUCE_GLYPHS (it);
23764 it->current_x += it->pixel_width;
23765 g++;
23766 }
23767
23768 it->area = TEXT_AREA;
23769 }
23770
23771
23772
23773 it->current_x = saved_x;
23774 it->object = saved_object;
23775 it->position = saved_pos;
23776 it->what = saved_what;
23777 it->face_id = orig_face_id;
23778 }
23779 }
23780
23781
23782
23783
23784
23785 static bool
23786 trailing_whitespace_p (ptrdiff_t charpos)
23787 {
23788 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23789 int c = 0;
23790
23791 while (bytepos < ZV_BYTE
23792 && (c = FETCH_BYTE (bytepos),
23793 c == ' ' || c == '\t'))
23794 ++bytepos;
23795
23796 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23797 {
23798 if (bytepos != PT_BYTE)
23799 return true;
23800 }
23801 return false;
23802 }
23803
23804
23805
23806
23807 static void
23808 highlight_trailing_whitespace (struct it *it)
23809 {
23810 struct glyph_row *row = it->glyph_row;
23811 int used = row->used[TEXT_AREA];
23812
23813 if (used)
23814 {
23815 struct glyph *start = row->glyphs[TEXT_AREA];
23816 struct glyph *glyph = start + used - 1;
23817
23818 if (row->reversed_p)
23819 {
23820
23821
23822 glyph = start;
23823 start = row->glyphs[TEXT_AREA] + used - 1;
23824 }
23825
23826
23827
23828
23829
23830 if (!row->reversed_p)
23831 {
23832 while (glyph >= start
23833 && (glyph->type == CHAR_GLYPH
23834 || glyph->type == STRETCH_GLYPH)
23835 && NILP (glyph->object))
23836 --glyph;
23837 }
23838 else
23839 {
23840 while (glyph <= start
23841 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23842 && NILP (glyph->object))
23843 ++glyph;
23844 }
23845
23846
23847
23848
23849 if ((row->reversed_p ? glyph <= start : glyph >= start)
23850 && BUFFERP (glyph->object)
23851 && (glyph->type == STRETCH_GLYPH
23852 || (glyph->type == CHAR_GLYPH
23853 && glyph->u.ch == ' '))
23854 && trailing_whitespace_p (glyph->charpos))
23855 {
23856 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23857 if (face_id < 0)
23858 return;
23859
23860 if (!row->reversed_p)
23861 {
23862 while (glyph >= start
23863 && BUFFERP (glyph->object)
23864 && (glyph->type == STRETCH_GLYPH
23865 || (glyph->type == CHAR_GLYPH
23866 && glyph->u.ch == ' ')))
23867 (glyph--)->face_id = face_id;
23868 }
23869 else
23870 {
23871 while (glyph <= start
23872 && BUFFERP (glyph->object)
23873 && (glyph->type == STRETCH_GLYPH
23874 || (glyph->type == CHAR_GLYPH
23875 && glyph->u.ch == ' ')))
23876 (glyph++)->face_id = face_id;
23877 }
23878 }
23879 }
23880 }
23881
23882
23883
23884
23885
23886 static bool
23887 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
23888 {
23889 bool result = true;
23890
23891 if (charpos == CHARPOS (row->end.pos)
23892 || charpos == MATRIX_ROW_END_CHARPOS (row))
23893 {
23894
23895
23896
23897
23898
23899
23900
23901
23902 if (CHARPOS (row->end.string_pos) >= 0)
23903 {
23904 if (row->continued_p)
23905 result = true;
23906 else
23907 {
23908
23909 struct glyph *beg = row->glyphs[TEXT_AREA];
23910 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
23911 struct glyph *glyph;
23912
23913 result = false;
23914 for (glyph = end; glyph >= beg; --glyph)
23915 if (STRINGP (glyph->object))
23916 {
23917 Lisp_Object prop
23918 = Fget_char_property (make_fixnum (charpos),
23919 Qdisplay, Qnil);
23920 result =
23921 (!NILP (prop)
23922 && display_prop_string_p (prop, glyph->object));
23923
23924
23925
23926 if (!result)
23927 {
23928 Lisp_Object s = glyph->object;
23929
23930 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
23931 {
23932 ptrdiff_t gpos = glyph->charpos;
23933
23934 if (!NILP (Fget_char_property (make_fixnum (gpos),
23935 Qcursor, s)))
23936 {
23937 result = true;
23938 break;
23939 }
23940 }
23941 }
23942 break;
23943 }
23944 }
23945 }
23946 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
23947 {
23948
23949
23950
23951
23952 if (!row->ends_in_ellipsis_p)
23953 result = row->continued_p;
23954 else
23955
23956
23957
23958
23959 result = false;
23960 }
23961
23962
23963 else
23964 result = row->ends_at_zv_p;
23965 }
23966
23967 return result;
23968 }
23969
23970
23971
23972
23973 static bool
23974 cursor_row_p (struct glyph_row *row)
23975 {
23976 return row_for_charpos_p (row, PT);
23977 }
23978
23979
23980
23981
23982
23983
23984
23985
23986 static bool
23987 push_prefix_prop (struct it *it, Lisp_Object prop)
23988 {
23989 struct text_pos pos =
23990 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
23991
23992 eassert (it->method == GET_FROM_BUFFER
23993 || it->method == GET_FROM_DISPLAY_VECTOR
23994 || it->method == GET_FROM_STRING
23995 || it->method == GET_FROM_IMAGE);
23996
23997
23998
23999
24000
24001 push_it (it, &pos);
24002
24003 if (STRINGP (prop))
24004 {
24005 if (SCHARS (prop) == 0)
24006 {
24007 pop_it (it);
24008 return false;
24009 }
24010
24011 it->string = prop;
24012 it->string_from_prefix_prop_p = true;
24013 it->multibyte_p = STRING_MULTIBYTE (it->string);
24014 it->current.overlay_string_index = -1;
24015 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24016 it->end_charpos = it->string_nchars = SCHARS (it->string);
24017 it->method = GET_FROM_STRING;
24018 it->stop_charpos = 0;
24019 it->prev_stop = 0;
24020 it->base_level_stop = 0;
24021 it->cmp_it.id = -1;
24022
24023
24024
24025 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24026 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24027 else
24028 it->paragraph_embedding = L2R;
24029
24030
24031 if (it->bidi_p)
24032 {
24033 it->bidi_it.string.lstring = it->string;
24034 it->bidi_it.string.s = NULL;
24035 it->bidi_it.string.schars = it->end_charpos;
24036 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24037 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24038 it->bidi_it.string.unibyte = !it->multibyte_p;
24039 it->bidi_it.w = it->w;
24040 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24041 }
24042 }
24043 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24044 {
24045 it->method = GET_FROM_STRETCH;
24046 it->object = prop;
24047 }
24048 #ifdef HAVE_WINDOW_SYSTEM
24049 else if (IMAGEP (prop))
24050 {
24051 it->what = IT_IMAGE;
24052 it->image_id = lookup_image (it->f, prop, it->face_id);
24053 it->method = GET_FROM_IMAGE;
24054 }
24055 #endif
24056 else
24057 {
24058 pop_it (it);
24059 return false;
24060 }
24061
24062 return true;
24063 }
24064
24065
24066
24067 static Lisp_Object
24068 get_it_property (struct it *it, Lisp_Object prop)
24069 {
24070 Lisp_Object position, object = it->object;
24071
24072 if (STRINGP (object))
24073 position = make_fixnum (IT_STRING_CHARPOS (*it));
24074 else if (BUFFERP (object))
24075 {
24076 position = make_fixnum (IT_CHARPOS (*it));
24077 object = it->window;
24078 }
24079 else
24080 return Qnil;
24081
24082 return Fget_char_property (position, prop, object);
24083 }
24084
24085
24086
24087
24088 static Lisp_Object
24089 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24090 {
24091 Lisp_Object prefix = get_it_property (it, prop);
24092
24093
24094
24095 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24096 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24097 it->w->contents);
24098 return prefix;
24099 }
24100
24101
24102
24103 static void
24104 handle_line_prefix (struct it *it)
24105 {
24106 Lisp_Object prefix;
24107
24108 if (it->continuation_lines_width > 0)
24109 {
24110 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24111 if (NILP (prefix))
24112 prefix = Vwrap_prefix;
24113 }
24114 else
24115 {
24116 prefix = get_line_prefix_it_property (it, Qline_prefix);
24117 if (NILP (prefix))
24118 prefix = Vline_prefix;
24119 }
24120 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24121 {
24122
24123
24124
24125 it->line_wrap = TRUNCATE;
24126 it->avoid_cursor_p = true;
24127 }
24128 }
24129
24130
24131
24132
24133
24134
24135
24136 static void
24137 unproduce_glyphs (struct it *it, int n)
24138 {
24139 struct glyph *glyph, *end;
24140
24141 eassert (it->glyph_row);
24142 eassert (it->glyph_row->reversed_p);
24143 eassert (it->area == TEXT_AREA);
24144 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24145
24146 if (n > it->glyph_row->used[TEXT_AREA])
24147 n = it->glyph_row->used[TEXT_AREA];
24148 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24149 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24150 for ( ; glyph < end; glyph++)
24151 glyph[-n] = *glyph;
24152 }
24153
24154
24155
24156 static void
24157 find_row_edges (struct it *it, struct glyph_row *row,
24158 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24159 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24160 {
24161
24162
24163
24164
24165
24166 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24167 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24168 else
24169
24170
24171
24172 row->minpos = row->start.pos;
24173 if (max_pos <= 0)
24174 {
24175 max_pos = CHARPOS (it->current.pos);
24176 max_bpos = BYTEPOS (it->current.pos);
24177 }
24178
24179
24180
24181
24182
24183
24184
24185
24186
24187
24188
24189
24190
24191
24192
24193
24194
24195 if (row->ends_at_zv_p)
24196 row->maxpos = it->current.pos;
24197 else if (row->used[TEXT_AREA])
24198 {
24199 bool seen_this_string = false;
24200 struct glyph_row *r1 = row - 1;
24201
24202
24203 if (STRINGP (it->object)
24204
24205 && row > it->w->desired_matrix->rows
24206
24207 && !r1->mode_line_p
24208
24209 && r1->ends_in_newline_from_string_p)
24210 {
24211 struct glyph *start, *end;
24212
24213
24214
24215
24216
24217 if (!r1->reversed_p)
24218 {
24219 start = r1->glyphs[TEXT_AREA];
24220 end = start + r1->used[TEXT_AREA];
24221
24222 while (end > start
24223 && NILP ((end - 1)->object)
24224 && (end - 1)->charpos <= 0)
24225 --end;
24226 if (end > start)
24227 {
24228 if (EQ ((end - 1)->object, it->object))
24229 seen_this_string = true;
24230 }
24231 else
24232
24233
24234
24235
24236
24237 seen_this_string = true;
24238 }
24239 else
24240 {
24241 end = r1->glyphs[TEXT_AREA] - 1;
24242 start = end + r1->used[TEXT_AREA];
24243 while (end < start
24244 && NILP ((end + 1)->object)
24245 && (end + 1)->charpos <= 0)
24246 ++end;
24247 if (end < start)
24248 {
24249 if (EQ ((end + 1)->object, it->object))
24250 seen_this_string = true;
24251 }
24252 else
24253 seen_this_string = true;
24254 }
24255 }
24256
24257
24258
24259 if (row->ends_in_newline_from_string_p && !seen_this_string)
24260 {
24261
24262
24263
24264
24265
24266
24267
24268
24269 if (CHARPOS (row->end.pos) > max_pos)
24270 inc_both (&max_pos, &max_bpos);
24271 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24272 }
24273 else if (CHARPOS (it->eol_pos) > 0)
24274 SET_TEXT_POS (row->maxpos,
24275 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24276 else if (row->continued_p)
24277 {
24278
24279
24280
24281
24282
24283
24284 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24285 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24286 else
24287 {
24288 inc_both (&max_pos, &max_bpos);
24289 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24290 }
24291 }
24292 else if (row->truncated_on_right_p)
24293
24294
24295
24296 row->maxpos = it->current.pos;
24297 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24298
24299 row->maxpos = row->minpos;
24300 else
24301 emacs_abort ();
24302 }
24303 else
24304 row->maxpos = it->current.pos;
24305 }
24306
24307
24308
24309 static ptrdiff_t
24310 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24311 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24312 {
24313 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24314 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24315
24316 ptrdiff_t val;
24317 specpdl_ref pdl_count = SPECPDL_INDEX ();
24318 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24319 labeled_restrictions_remove_in_current_buffer ();
24320 Fwiden ();
24321 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24322 unbind_to (pdl_count, Qnil);
24323 return val;
24324 }
24325
24326
24327
24328 static ptrdiff_t
24329 display_count_lines_visually (struct it *it)
24330 {
24331 struct it tem_it;
24332 ptrdiff_t to;
24333 struct text_pos from;
24334
24335
24336
24337
24338
24339
24340 if (it->lnum_bytepos > 0)
24341 return it->lnum + 1;
24342 else
24343 {
24344 specpdl_ref count = SPECPDL_INDEX ();
24345
24346 if (IT_CHARPOS (*it) <= PT)
24347 {
24348 from = it->current.pos;
24349 to = PT;
24350 }
24351 else
24352 {
24353 SET_TEXT_POS (from, PT, PT_BYTE);
24354 to = IT_CHARPOS (*it);
24355 }
24356
24357
24358
24359 specbind (Qdisplay_line_numbers, Qrelative);
24360 start_display (&tem_it, it->w, from);
24361
24362
24363
24364
24365 move_it_to (&tem_it, to, -1,
24366 tem_it.last_visible_y
24367 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24368 -1, MOVE_TO_POS | MOVE_TO_Y);
24369 unbind_to (count, Qnil);
24370 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24371 }
24372 }
24373
24374
24375
24376
24377 static void
24378 maybe_produce_line_number (struct it *it)
24379 {
24380 ptrdiff_t last_line = it->lnum;
24381 ptrdiff_t start_from, bytepos;
24382 ptrdiff_t this_line;
24383 bool first_time = false;
24384 ptrdiff_t beg_byte;
24385 ptrdiff_t z_byte;
24386 bool line_numbers_wide;
24387 void *itdata = bidi_shelve_cache ();
24388
24389 if (display_line_numbers_offset
24390 && !display_line_numbers_widen
24391 && !EQ (Vdisplay_line_numbers, Qvisual)
24392 && !EQ (Vdisplay_line_numbers, Qrelative))
24393 line_numbers_wide = true;
24394 else
24395 line_numbers_wide = display_line_numbers_widen;
24396
24397 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24398 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24399
24400 if (EQ (Vdisplay_line_numbers, Qvisual))
24401 this_line = display_count_lines_visually (it);
24402 else
24403 {
24404 if (!last_line)
24405 {
24406
24407 if (it->w->base_line_number > 0
24408 && it->w->base_line_pos > 0
24409 && it->w->base_line_pos <= IT_CHARPOS (*it)
24410
24411
24412
24413
24414 && !(line_numbers_wide
24415 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24416 && !current_buffer->clip_changed)
24417 {
24418 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24419 last_line = it->w->base_line_number - 1;
24420 }
24421 else
24422 start_from = beg_byte;
24423 if (!it->lnum_bytepos)
24424 first_time = true;
24425 }
24426 else
24427 start_from = it->lnum_bytepos;
24428
24429
24430
24431
24432 if (!(beg_byte <= start_from && start_from <= z_byte))
24433 {
24434 last_line = 0;
24435 start_from = beg_byte;
24436 }
24437
24438 this_line =
24439 last_line + display_count_lines_logically (start_from,
24440 IT_BYTEPOS (*it),
24441 IT_CHARPOS (*it), &bytepos);
24442 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24443 eassert (bytepos == IT_BYTEPOS (*it));
24444 }
24445
24446
24447 if (this_line != last_line || !it->lnum_bytepos)
24448 {
24449 it->lnum = this_line;
24450 it->lnum_bytepos = IT_BYTEPOS (*it);
24451 }
24452
24453
24454 struct it tem_it;
24455 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24456 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24457 ptrdiff_t lnum_offset = -1;
24458 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24459 int current_lnum_face_id
24460 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24461
24462
24463 bool save_free_realized_faces = inhibit_free_realized_faces;
24464 inhibit_free_realized_faces = true;
24465
24466 if ((EQ (Vdisplay_line_numbers, Qrelative)
24467 || EQ (Vdisplay_line_numbers, Qvisual)
24468 || lnum_face_id != current_lnum_face_id)
24469 && !it->pt_lnum)
24470 {
24471 ptrdiff_t ignored;
24472 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24473 it->pt_lnum =
24474 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24475 PT, &ignored);
24476 else
24477 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24478 &ignored);
24479 }
24480
24481 if (!it->lnum_width)
24482 {
24483 if (FIXNATP (Vdisplay_line_numbers_width))
24484 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24485
24486
24487
24488 ptrdiff_t max_lnum;
24489
24490 if (NILP (Vdisplay_line_numbers_current_absolute)
24491 && (EQ (Vdisplay_line_numbers, Qrelative)
24492 || EQ (Vdisplay_line_numbers, Qvisual)))
24493
24494
24495 max_lnum = it->w->desired_matrix->nrows - 2;
24496 else if (EQ (Vdisplay_line_numbers, Qvisual))
24497 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24498 else
24499 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24500 max_lnum = max (1, max_lnum);
24501 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24502 eassert (it->lnum_width > 0);
24503 }
24504 if (EQ (Vdisplay_line_numbers, Qrelative))
24505 lnum_offset = it->pt_lnum;
24506 else if (EQ (Vdisplay_line_numbers, Qvisual))
24507 lnum_offset = 0;
24508 else if (display_line_numbers_offset)
24509 lnum_offset -= display_line_numbers_offset;
24510
24511
24512
24513 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24514 if ((EQ (Vdisplay_line_numbers, Qrelative)
24515 || EQ (Vdisplay_line_numbers, Qvisual))
24516 && lnum_to_display == 0
24517 && !NILP (Vdisplay_line_numbers_current_absolute))
24518 lnum_to_display = it->pt_lnum + 1;
24519
24520
24521
24522
24523
24524 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24525 strcat (lnum_buf, " ");
24526
24527
24528 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24529
24530 DEFAULT_FACE_ID);
24531 scratch_glyph_row.reversed_p = false;
24532 scratch_glyph_row.used[TEXT_AREA] = 0;
24533 SET_TEXT_POS (tem_it.position, 0, 0);
24534 tem_it.avoid_cursor_p = true;
24535 tem_it.bidi_p = true;
24536 tem_it.bidi_it.type = WEAK_EN;
24537
24538
24539
24540 tem_it.bidi_it.resolved_level = 2;
24541
24542
24543
24544 int width_limit =
24545 tem_it.last_visible_x - tem_it.first_visible_x
24546 - 3 * FRAME_COLUMN_WIDTH (it->f);
24547
24548 tem_it.face_id = lnum_face_id;
24549
24550
24551 if (lnum_face_id != current_lnum_face_id
24552 && (EQ (Vdisplay_line_numbers, Qvisual)
24553 ? this_line == 0
24554 : this_line == it->pt_lnum)
24555 && it->what != IT_EOB)
24556 tem_it.face_id = current_lnum_face_id;
24557 else if (!beyond_zv)
24558 {
24559 if (display_line_numbers_major_tick > 0
24560 && (lnum_to_display % display_line_numbers_major_tick == 0))
24561 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24562 0, DEFAULT_FACE_ID);
24563 else if (display_line_numbers_minor_tick > 0
24564 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24565 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24566 0, DEFAULT_FACE_ID);
24567 }
24568
24569
24570 for (const char *p = lnum_buf; *p; p++)
24571 {
24572
24573
24574 if (beyond_zv
24575
24576 || (!EQ (Vdisplay_line_numbers, Qvisual)
24577 && (it->continuation_lines_width > 0
24578 || (this_line == last_line && !first_time))))
24579 tem_it.c = tem_it.char_to_display = ' ';
24580 else
24581 tem_it.c = tem_it.char_to_display = *p;
24582 tem_it.len = 1;
24583
24584 SET_TEXT_POS (tem_it.position, -1, -1);
24585 PRODUCE_GLYPHS (&tem_it);
24586
24587
24588
24589 if (tem_it.current_x >= width_limit)
24590 {
24591 it->lnum_width = 0;
24592 it->lnum_pixel_width = 0;
24593 bidi_unshelve_cache (itdata, false);
24594 inhibit_free_realized_faces = save_free_realized_faces;
24595 return;
24596 }
24597 }
24598
24599 inhibit_free_realized_faces = save_free_realized_faces;
24600
24601
24602 it->lnum_pixel_width = tem_it.current_x;
24603
24604 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24605 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24606 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24607 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24608
24609 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24610
24611 for ( ; g < e; g++)
24612 {
24613 it->current_x += g->pixel_width;
24614
24615
24616
24617 if (it->current_x > it->first_visible_x)
24618 it->hpos++;
24619 if (p)
24620 {
24621 *p++ = *g;
24622 (*u)++;
24623 }
24624 }
24625
24626
24627
24628
24629 if (!beyond_zv)
24630 {
24631 if (it->glyph_row)
24632 {
24633 struct glyph_row *row = it->glyph_row;
24634
24635 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24636 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24637 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24638 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24639 tem_it.max_phys_descent);
24640 }
24641 else
24642 {
24643 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24644 it->max_descent = max (it->max_descent, tem_it.max_descent);
24645 it->max_phys_ascent = max (it->max_phys_ascent,
24646 tem_it.max_phys_ascent);
24647 it->max_phys_descent = max (it->max_phys_descent,
24648 tem_it.max_phys_descent);
24649 }
24650 }
24651
24652 it->line_number_produced_p = true;
24653
24654 bidi_unshelve_cache (itdata, false);
24655 }
24656
24657
24658
24659 static bool
24660 should_produce_line_number (struct it *it)
24661 {
24662 if (NILP (Vdisplay_line_numbers))
24663 return false;
24664
24665
24666 if (MINI_WINDOW_P (it->w))
24667 return false;
24668
24669 #ifdef HAVE_WINDOW_SYSTEM
24670
24671 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24672 return false;
24673 #endif
24674
24675
24676
24677
24678
24679 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24680 Qdisplay_line_numbers_disable,
24681 it->window);
24682
24683
24684
24685 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24686 val = disable_line_numbers_overlay_at_eob ();
24687 return NILP (val) ? true : false;
24688 }
24689
24690
24691
24692
24693
24694 static bool
24695 row_text_area_empty (struct glyph_row *row)
24696 {
24697 if (!row->reversed_p)
24698 {
24699 for (struct glyph *g = row->glyphs[TEXT_AREA];
24700 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24701 g++)
24702 if (!NILP (g->object) || g->charpos > 0)
24703 return false;
24704 }
24705 else
24706 {
24707 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24708 g > row->glyphs[TEXT_AREA];
24709 g--)
24710 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24711 return false;
24712 }
24713
24714 return true;
24715 }
24716
24717
24718
24719
24720
24721
24722
24723
24724 static bool
24725 display_line (struct it *it, int cursor_vpos)
24726 {
24727 struct glyph_row *row = it->glyph_row;
24728 Lisp_Object overlay_arrow_string;
24729 struct it wrap_it;
24730 void *wrap_data = NULL;
24731 bool may_wrap = false;
24732 int wrap_x UNINIT;
24733 int wrap_row_used = -1;
24734 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24735 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24736 int wrap_row_extra_line_spacing UNINIT;
24737 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24738 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24739 int cvpos;
24740 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24741 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24742 bool pending_handle_line_prefix = false;
24743 int tab_line = window_wants_tab_line (it->w);
24744 int header_line = window_wants_header_line (it->w);
24745 bool hscroll_this_line = (cursor_vpos >= 0
24746 && it->vpos == cursor_vpos - tab_line - header_line
24747 && hscrolling_current_line_p (it->w));
24748 int first_visible_x = it->first_visible_x;
24749 int last_visible_x = it->last_visible_x;
24750 int x_incr = 0;
24751
24752
24753 eassert (it->hpos == 0 && it->current_x == 0);
24754
24755 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24756 >= it->w->desired_matrix->nrows)
24757 {
24758 it->w->nrows_scale_factor++;
24759 it->f->fonts_changed = true;
24760 return false;
24761 }
24762
24763
24764 prepare_desired_row (it->w, row, false);
24765
24766 row->y = it->current_y;
24767 row->start = it->start;
24768 row->continuation_lines_width = it->continuation_lines_width;
24769 row->displays_text_p = true;
24770 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24771 it->starts_in_middle_of_char_p = false;
24772 it->stretch_adjust = 0;
24773 it->line_number_produced_p = false;
24774
24775
24776
24777
24778 if (hscroll_this_line)
24779 x_incr =
24780 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24781 * FRAME_COLUMN_WIDTH (it->f);
24782
24783 bool line_number_needed = should_produce_line_number (it);
24784
24785
24786
24787
24788 if (it->current_x < it->first_visible_x + x_incr)
24789 {
24790 enum move_it_result move_result;
24791
24792 this_line_min_pos = row->start.pos;
24793 if (hscroll_this_line)
24794 {
24795 it->first_visible_x += x_incr;
24796 it->last_visible_x += x_incr;
24797 }
24798 if (current_buffer->long_line_optimizations_p
24799 && it->line_wrap == TRUNCATE
24800 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24801 {
24802
24803
24804
24805
24806 ptrdiff_t chars_to_skip =
24807 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24808 move_result = fast_move_it_horizontally (it, chars_to_skip);
24809
24810 if (move_result == MOVE_X_REACHED)
24811 it->current_x = it->first_visible_x;
24812 else
24813 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24814 }
24815 else
24816 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24817 MOVE_TO_POS | MOVE_TO_X);
24818
24819
24820
24821
24822
24823
24824 if (it->current_x < it->first_visible_x
24825 && (move_result == MOVE_NEWLINE_OR_CR
24826 || move_result == MOVE_POS_MATCH_OR_ZV))
24827 it->current_x = it->first_visible_x;
24828
24829
24830
24831 it->line_number_produced_p = false;
24832
24833
24834
24835
24836
24837
24838
24839
24840 min_pos = CHARPOS (this_line_min_pos);
24841 min_bpos = BYTEPOS (this_line_min_pos);
24842
24843
24844 if (line_number_needed)
24845 maybe_produce_line_number (it);
24846 }
24847 else if (it->area == TEXT_AREA)
24848 {
24849
24850 if (line_number_needed)
24851 maybe_produce_line_number (it);
24852
24853
24854
24855 handle_line_prefix (it);
24856 }
24857 else
24858 {
24859
24860
24861
24862
24863
24864
24865
24866 pending_handle_line_prefix = true;
24867 }
24868
24869
24870
24871 row->ascent = it->max_ascent;
24872 row->height = it->max_ascent + it->max_descent;
24873 row->phys_ascent = it->max_phys_ascent;
24874 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24875 row->extra_line_spacing = it->max_extra_line_spacing;
24876
24877
24878 #define RECORD_MAX_MIN_POS(IT) \
24879 do \
24880 { \
24881 bool composition_p \
24882 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
24883 ptrdiff_t current_pos = \
24884 composition_p ? (IT)->cmp_it.charpos \
24885 : IT_CHARPOS (*(IT)); \
24886 ptrdiff_t current_bpos = \
24887 composition_p ? CHAR_TO_BYTE (current_pos) \
24888 : IT_BYTEPOS (*(IT)); \
24889 if (current_pos < min_pos) \
24890 { \
24891 min_pos = current_pos; \
24892 min_bpos = current_bpos; \
24893 } \
24894 if (IT_CHARPOS (*it) > max_pos) \
24895 { \
24896 max_pos = IT_CHARPOS (*it); \
24897 max_bpos = IT_BYTEPOS (*it); \
24898 } \
24899 } \
24900 while (false)
24901
24902
24903
24904 while (true)
24905 {
24906 int n_glyphs_before, hpos_before, x_before;
24907 int x, nglyphs;
24908 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
24909
24910
24911
24912 if (!get_next_display_element (it))
24913 {
24914 bool row_has_glyphs = false;
24915
24916
24917
24918
24919 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
24920 row->exact_window_width_line_p = true;
24921 else if ((append_space_for_newline (it, true)
24922 && row->used[TEXT_AREA] == 1)
24923 || row->used[TEXT_AREA] == 0
24924 || (row_has_glyphs = row_text_area_empty (row)))
24925 {
24926 row->glyphs[TEXT_AREA]->charpos = -1;
24927
24928
24929 if (!row_has_glyphs)
24930 row->displays_text_p = false;
24931
24932 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
24933 && (!MINI_WINDOW_P (it->w)))
24934 row->indicate_empty_line_p = true;
24935 }
24936
24937 it->continuation_lines_width = 0;
24938
24939
24940
24941
24942 it->font_height = Qnil;
24943 it->voffset = 0;
24944 row->ends_at_zv_p = true;
24945
24946
24947
24948
24949
24950
24951
24952
24953 if (row->reversed_p
24954 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
24955 != DEFAULT_FACE_ID)
24956 extend_face_to_end_of_line (it);
24957 break;
24958 }
24959
24960
24961
24962 n_glyphs_before = row->used[TEXT_AREA];
24963 x = it->current_x;
24964
24965
24966
24967 if (it->line_wrap != TRUNCATE)
24968 {
24969 ascent = it->max_ascent;
24970 descent = it->max_descent;
24971 phys_ascent = it->max_phys_ascent;
24972 phys_descent = it->max_phys_descent;
24973
24974 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
24975 {
24976 bool next_may_wrap = may_wrap;
24977
24978 if (char_can_wrap_after (it))
24979 next_may_wrap = true;
24980 else
24981 next_may_wrap = false;
24982
24983 if (may_wrap && char_can_wrap_before (it))
24984 {
24985 SAVE_IT (wrap_it, *it, wrap_data);
24986 wrap_x = x;
24987 wrap_row_used = row->used[TEXT_AREA];
24988 wrap_row_ascent = row->ascent;
24989 wrap_row_height = row->height;
24990 wrap_row_phys_ascent = row->phys_ascent;
24991 wrap_row_phys_height = row->phys_height;
24992 wrap_row_extra_line_spacing = row->extra_line_spacing;
24993 wrap_row_min_pos = min_pos;
24994 wrap_row_min_bpos = min_bpos;
24995 wrap_row_max_pos = max_pos;
24996 wrap_row_max_bpos = max_bpos;
24997 }
24998
24999 may_wrap = next_may_wrap;
25000 }
25001 }
25002
25003 PRODUCE_GLYPHS (it);
25004
25005
25006
25007 if (it->area != TEXT_AREA)
25008 {
25009 row->ascent = max (row->ascent, it->max_ascent);
25010 row->height = max (row->height, it->max_ascent + it->max_descent);
25011 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25012 row->phys_height = max (row->phys_height,
25013 it->max_phys_ascent + it->max_phys_descent);
25014 row->extra_line_spacing = max (row->extra_line_spacing,
25015 it->max_extra_line_spacing);
25016 set_iterator_to_next (it, true);
25017
25018
25019
25020 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25021 {
25022
25023 if (line_number_needed)
25024 maybe_produce_line_number (it);
25025
25026 pending_handle_line_prefix = false;
25027 handle_line_prefix (it);
25028 }
25029 continue;
25030 }
25031
25032
25033
25034
25035
25036
25037
25038
25039
25040
25041 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25042 hpos_before = it->hpos;
25043 x_before = x;
25044
25045 if (
25046 nglyphs > 0
25047
25048 && it->current_x < it->last_visible_x)
25049 {
25050 it->hpos += nglyphs;
25051 row->ascent = max (row->ascent, it->max_ascent);
25052 row->height = max (row->height, it->max_ascent + it->max_descent);
25053 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25054 row->phys_height = max (row->phys_height,
25055 it->max_phys_ascent + it->max_phys_descent);
25056 row->extra_line_spacing = max (row->extra_line_spacing,
25057 it->max_extra_line_spacing);
25058 if (it->current_x - it->pixel_width < it->first_visible_x
25059
25060
25061
25062 && !line_number_needed
25063
25064
25065
25066
25067 && !row->reversed_p)
25068 row->x = x - it->first_visible_x;
25069
25070
25071 if (it->bidi_p)
25072 RECORD_MAX_MIN_POS (it);
25073 }
25074 else
25075 {
25076 int i, new_x;
25077 struct glyph *glyph;
25078
25079 for (i = 0; i < nglyphs; ++i, x = new_x)
25080 {
25081
25082
25083
25084 if (!row->reversed_p)
25085 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25086 else
25087 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25088 new_x = x + glyph->pixel_width;
25089
25090 if (
25091 it->line_wrap != TRUNCATE
25092 && (
25093 new_x > it->last_visible_x
25094
25095 || (new_x == it->last_visible_x
25096 && FRAME_WINDOW_P (it->f)
25097 && (row->reversed_p
25098 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25099 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25100 {
25101
25102
25103 if (it->hpos == 0
25104 || (new_x == it->last_visible_x
25105 && FRAME_WINDOW_P (it->f)
25106 && (row->reversed_p
25107 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25108 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25109 {
25110
25111
25112
25113
25114 row->continued_p = true;
25115 it->current_x = new_x;
25116 it->continuation_lines_width += new_x;
25117 ++it->hpos;
25118 if (i == nglyphs - 1)
25119 {
25120
25121
25122 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25123 && wrap_row_used > 0
25124
25125
25126
25127
25128
25129
25130
25131
25132
25133
25134 && (!may_wrap || !char_can_wrap_before (it)))
25135 goto back_to_wrap;
25136
25137
25138
25139
25140 if (it->bidi_p)
25141 RECORD_MAX_MIN_POS (it);
25142 set_iterator_to_next (it, true);
25143 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25144 {
25145 if (!get_next_display_element (it))
25146 {
25147 row->exact_window_width_line_p = true;
25148 it->continuation_lines_width = 0;
25149 it->font_height = Qnil;
25150 it->voffset = 0;
25151 row->continued_p = false;
25152 row->ends_at_zv_p = true;
25153 }
25154 else if (ITERATOR_AT_END_OF_LINE_P (it))
25155 {
25156 row->continued_p = false;
25157 row->exact_window_width_line_p = true;
25158 }
25159
25160
25161 else if (wrap_row_used > 0
25162
25163
25164
25165
25166
25167
25168
25169
25170
25171 && (!may_wrap || !char_can_wrap_before (it)))
25172 goto back_to_wrap;
25173
25174 }
25175 }
25176 else if (it->bidi_p)
25177 RECORD_MAX_MIN_POS (it);
25178 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25179 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25180 extend_face_to_end_of_line (it);
25181 }
25182 else if (CHAR_GLYPH_PADDING_P (*glyph)
25183 && !FRAME_WINDOW_P (it->f))
25184 {
25185
25186
25187
25188 if (row->reversed_p)
25189 unproduce_glyphs (it, row->used[TEXT_AREA]
25190 - n_glyphs_before);
25191 row->used[TEXT_AREA] = n_glyphs_before;
25192
25193
25194
25195 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25196 < row->glyphs[1 + TEXT_AREA])
25197 produce_special_glyphs (it, IT_CONTINUATION);
25198
25199 row->continued_p = true;
25200 it->current_x = x_before;
25201 it->continuation_lines_width += x_before;
25202
25203
25204
25205 it->max_ascent = ascent;
25206 it->max_descent = descent;
25207 it->max_phys_ascent = phys_ascent;
25208 it->max_phys_descent = phys_descent;
25209 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25210 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25211 extend_face_to_end_of_line (it);
25212 }
25213 else if (wrap_row_used > 0)
25214 {
25215 back_to_wrap:
25216 if (row->reversed_p)
25217 unproduce_glyphs (it,
25218 row->used[TEXT_AREA] - wrap_row_used);
25219 RESTORE_IT (it, &wrap_it, wrap_data);
25220 it->continuation_lines_width += wrap_x;
25221 row->used[TEXT_AREA] = wrap_row_used;
25222 row->ascent = wrap_row_ascent;
25223 row->height = wrap_row_height;
25224 row->phys_ascent = wrap_row_phys_ascent;
25225 row->phys_height = wrap_row_phys_height;
25226 row->extra_line_spacing = wrap_row_extra_line_spacing;
25227 min_pos = wrap_row_min_pos;
25228 min_bpos = wrap_row_min_bpos;
25229 max_pos = wrap_row_max_pos;
25230 max_bpos = wrap_row_max_bpos;
25231 row->continued_p = true;
25232 row->ends_at_zv_p = false;
25233 row->exact_window_width_line_p = false;
25234
25235
25236
25237 extend_face_to_end_of_line (it);
25238 }
25239 else if ((it->what == IT_CHARACTER
25240 || it->what == IT_STRETCH
25241 || it->what == IT_COMPOSITION)
25242 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25243 {
25244
25245
25246
25247
25248
25249 if ((row->reversed_p
25250 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25251 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25252 produce_special_glyphs (it, IT_CONTINUATION);
25253 it->continuation_lines_width += it->last_visible_x;
25254 row->ends_in_middle_of_char_p = true;
25255 row->continued_p = true;
25256 glyph->pixel_width = it->last_visible_x - x;
25257 it->starts_in_middle_of_char_p = true;
25258 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25259 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25260 extend_face_to_end_of_line (it);
25261 }
25262 else
25263 {
25264
25265
25266
25267 if (row->reversed_p)
25268 unproduce_glyphs (it, row->used[TEXT_AREA]
25269 - (n_glyphs_before + i));
25270 row->used[TEXT_AREA] = n_glyphs_before + i;
25271
25272
25273 it->current_x = x_before;
25274 it->continuation_lines_width += x;
25275 if (!FRAME_WINDOW_P (it->f)
25276 || (row->reversed_p
25277 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25278 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25279 produce_special_glyphs (it, IT_CONTINUATION);
25280 row->continued_p = true;
25281
25282 extend_face_to_end_of_line (it);
25283
25284 if (nglyphs > 1 && i > 0)
25285 {
25286 row->ends_in_middle_of_char_p = true;
25287 it->starts_in_middle_of_char_p = true;
25288 }
25289
25290
25291
25292 it->max_ascent = ascent;
25293 it->max_descent = descent;
25294 it->max_phys_ascent = phys_ascent;
25295 it->max_phys_descent = phys_descent;
25296 }
25297
25298 break;
25299 }
25300 else if (new_x > it->first_visible_x)
25301 {
25302
25303 ++it->hpos;
25304
25305
25306
25307
25308 if (it->bidi_p)
25309 RECORD_MAX_MIN_POS (it);
25310
25311 if (x < it->first_visible_x && !row->reversed_p
25312 && !line_number_needed)
25313
25314
25315
25316
25317
25318
25319 row->x = x - it->first_visible_x;
25320
25321
25322
25323
25324
25325
25326 if (row->reversed_p
25327 && new_x > it->last_visible_x
25328 && !line_number_needed
25329 && !(it->line_wrap == TRUNCATE
25330 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25331 {
25332 eassert (FRAME_WINDOW_P (it->f));
25333 row->x = it->last_visible_x - new_x;
25334 }
25335 }
25336 else
25337 {
25338
25339
25340
25341
25342
25343 eassert (it->first_visible_x <= it->last_visible_x);
25344 }
25345 }
25346
25347
25348 if (it->bidi_p && nglyphs == 0)
25349 RECORD_MAX_MIN_POS (it);
25350
25351 row->ascent = max (row->ascent, it->max_ascent);
25352 row->height = max (row->height, it->max_ascent + it->max_descent);
25353 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25354 row->phys_height = max (row->phys_height,
25355 it->max_phys_ascent + it->max_phys_descent);
25356 row->extra_line_spacing = max (row->extra_line_spacing,
25357 it->max_extra_line_spacing);
25358
25359
25360 if (row->continued_p || row->ends_at_zv_p)
25361 break;
25362 }
25363
25364 at_end_of_line:
25365
25366
25367
25368 if (ITERATOR_AT_END_OF_LINE_P (it))
25369 {
25370 int used_before = row->used[TEXT_AREA];
25371
25372 row->ends_in_newline_from_string_p = STRINGP (it->object);
25373
25374
25375
25376 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25377 append_space_for_newline (it, false);
25378
25379
25380 extend_face_to_end_of_line (it);
25381
25382
25383 if (used_before == 0)
25384 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25385
25386
25387
25388 it->eol_pos = it->current.pos;
25389
25390
25391 set_iterator_to_next (it, true);
25392 it->continuation_lines_width = 0;
25393 break;
25394 }
25395
25396
25397
25398
25399
25400
25401
25402
25403 bool overwide_wrap_prefix =
25404 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25405 && it->sp > 0 && it->method == GET_FROM_STRETCH
25406 && it->current_x >= it->last_visible_x
25407 && it->continuation_lines_width > 0
25408 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25409
25410
25411
25412 if (!overwide_wrap_prefix)
25413 set_iterator_to_next (it, true);
25414
25415
25416
25417 if (it->line_wrap == TRUNCATE
25418 && ((FRAME_WINDOW_P (it->f)
25419
25420
25421
25422
25423 && ((row->reversed_p
25424 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25425 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25426 || it->what == IT_IMAGE))
25427 ? (it->current_x >= it->last_visible_x)
25428 : (it->current_x > it->last_visible_x)))
25429 {
25430
25431 if (!FRAME_WINDOW_P (it->f)
25432 || (row->reversed_p
25433 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25434 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25435 {
25436 int i, n;
25437
25438 if (!row->reversed_p)
25439 {
25440 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25441 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25442 break;
25443 }
25444 else
25445 {
25446 for (i = 0; i < row->used[TEXT_AREA]; i++)
25447 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25448 break;
25449
25450
25451
25452
25453
25454 unproduce_glyphs (it, i + 1);
25455
25456 i = row->used[TEXT_AREA] - (i + 1);
25457 }
25458
25459
25460
25461
25462 if (it->current_x > it->last_visible_x)
25463 {
25464 it->current_x = x_before;
25465 if (!FRAME_WINDOW_P (it->f))
25466 {
25467 for (n = row->used[TEXT_AREA]; i < n; ++i)
25468 {
25469 row->used[TEXT_AREA] = i;
25470 produce_special_glyphs (it, IT_TRUNCATION);
25471 }
25472 }
25473 else
25474 {
25475 row->used[TEXT_AREA] = i;
25476 produce_special_glyphs (it, IT_TRUNCATION);
25477 }
25478 it->hpos = hpos_before;
25479 }
25480 }
25481 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25482 {
25483
25484 if (!get_next_display_element (it))
25485 {
25486 it->continuation_lines_width = 0;
25487 it->font_height = Qnil;
25488 it->voffset = 0;
25489 row->ends_at_zv_p = true;
25490 row->exact_window_width_line_p = true;
25491 break;
25492 }
25493 if (ITERATOR_AT_END_OF_LINE_P (it))
25494 {
25495 row->exact_window_width_line_p = true;
25496 goto at_end_of_line;
25497 }
25498 it->current_x = x_before;
25499 it->hpos = hpos_before;
25500 }
25501
25502 row->truncated_on_right_p = true;
25503 it->continuation_lines_width = 0;
25504 reseat_at_next_visible_line_start (it, false);
25505
25506
25507
25508
25509 if (IT_BYTEPOS (*it) > BEG_BYTE)
25510 row->ends_at_zv_p =
25511 IT_BYTEPOS (*it) >= ZV_BYTE
25512 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25513 else
25514 row->ends_at_zv_p = false;
25515 break;
25516 }
25517 }
25518
25519 if (wrap_data)
25520 bidi_unshelve_cache (wrap_data, true);
25521
25522
25523
25524 if (it->first_visible_x
25525 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25526 {
25527 if (!FRAME_WINDOW_P (it->f)
25528 || (((row->reversed_p
25529 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25530 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25531
25532
25533 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25534 insert_left_trunc_glyphs (it);
25535 row->truncated_on_left_p = true;
25536 }
25537
25538
25539
25540
25541
25542
25543 row->end = it->current;
25544 if (!it->bidi_p)
25545 {
25546 row->minpos = row->start.pos;
25547 row->maxpos = row->end.pos;
25548 }
25549 else
25550 {
25551
25552
25553
25554
25555 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25556 }
25557
25558
25559
25560
25561
25562 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25563 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25564 !NILP (overlay_arrow_string)))
25565 {
25566
25567 if (STRINGP (overlay_arrow_string))
25568 {
25569 struct glyph_row *arrow_row
25570 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25571 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25572 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25573 struct glyph *p = row->glyphs[TEXT_AREA];
25574 struct glyph *p2, *end;
25575
25576
25577 while (glyph < arrow_end)
25578 *p++ = *glyph++;
25579
25580
25581 p2 = p;
25582 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25583 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25584 ++p2;
25585 if (p2 > p)
25586 {
25587 while (p2 < end)
25588 *p++ = *p2++;
25589 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25590 }
25591 }
25592 else
25593 {
25594 eassert (FIXNUMP (overlay_arrow_string));
25595 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25596 }
25597 overlay_arrow_seen = true;
25598 }
25599
25600
25601 if (!NILP (Vshow_trailing_whitespace))
25602 highlight_trailing_whitespace (it);
25603
25604
25605 compute_line_metrics (it);
25606
25607
25608
25609
25610
25611
25612
25613 row->ends_in_ellipsis_p
25614 = (it->method == GET_FROM_DISPLAY_VECTOR
25615 && it->ellipsis_p);
25616
25617
25618 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25619 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25620 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25621 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25622
25623 it->left_user_fringe_bitmap = 0;
25624 it->left_user_fringe_face_id = 0;
25625 it->right_user_fringe_bitmap = 0;
25626 it->right_user_fringe_face_id = 0;
25627
25628
25629
25630
25631
25632
25633 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25634 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25635 row->redraw_fringe_bitmaps_p = true;
25636
25637
25638 cvpos = it->w->cursor.vpos;
25639 if ((cvpos < 0
25640
25641
25642
25643
25644
25645
25646
25647
25648 || (it->bidi_p
25649 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25650 && PT >= MATRIX_ROW_START_CHARPOS (row)
25651 && PT <= MATRIX_ROW_END_CHARPOS (row)
25652 && cursor_row_p (row))
25653 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25654
25655
25656
25657
25658
25659 it->current_x = it->hpos = 0;
25660 it->current_y += row->height;
25661
25662
25663 if (hscroll_this_line)
25664 {
25665 it->first_visible_x = first_visible_x;
25666 it->last_visible_x = last_visible_x;
25667 }
25668 SET_TEXT_POS (it->eol_pos, 0, 0);
25669 ++it->vpos;
25670 ++it->glyph_row;
25671
25672
25673
25674
25675 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25676 it->glyph_row->reversed_p = row->reversed_p;
25677 it->start = row->end;
25678 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25679
25680 #undef RECORD_MAX_MIN_POS
25681 }
25682
25683 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25684 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25685 doc:
25686
25687
25688
25689
25690
25691
25692
25693
25694 )
25695 (Lisp_Object buffer)
25696 {
25697 struct buffer *buf = current_buffer;
25698 struct buffer *old = buf;
25699
25700 if (! NILP (buffer))
25701 {
25702 CHECK_BUFFER (buffer);
25703 buf = XBUFFER (buffer);
25704 }
25705
25706 if (NILP (BVAR (buf, bidi_display_reordering))
25707 || NILP (BVAR (buf, enable_multibyte_characters))
25708
25709
25710 || redisplay__inhibit_bidi)
25711 return Qleft_to_right;
25712 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25713 return BVAR (buf, bidi_paragraph_direction);
25714 else
25715 {
25716
25717
25718
25719 struct bidi_it itb;
25720 ptrdiff_t pos = BUF_PT (buf);
25721 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25722 int c;
25723 void *itb_data = bidi_shelve_cache ();
25724
25725 set_buffer_temp (buf);
25726
25727
25728
25729
25730
25731 if (pos >= ZV && pos > BEGV)
25732 dec_both (&pos, &bytepos);
25733 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25734 if (fast_looking_at (trailing_white_space,
25735 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25736 {
25737 while ((c = FETCH_BYTE (bytepos)) == '\n'
25738 || c == ' ' || c == '\t' || c == '\f')
25739 {
25740 if (bytepos <= BEGV_BYTE)
25741 break;
25742 bytepos--;
25743 pos--;
25744 }
25745 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25746 bytepos--;
25747 }
25748 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25749 itb.paragraph_dir = NEUTRAL_DIR;
25750 itb.string.s = NULL;
25751 itb.string.lstring = Qnil;
25752 itb.string.bufpos = 0;
25753 itb.string.from_disp_str = false;
25754 itb.string.unibyte = false;
25755
25756
25757
25758 itb.w = NULL;
25759 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25760 bidi_unshelve_cache (itb_data, false);
25761 set_buffer_temp (old);
25762 switch (itb.paragraph_dir)
25763 {
25764 case L2R:
25765 return Qleft_to_right;
25766 break;
25767 case R2L:
25768 return Qright_to_left;
25769 break;
25770 default:
25771 emacs_abort ();
25772 }
25773 }
25774 }
25775
25776 DEFUN ("bidi-find-overridden-directionality",
25777 Fbidi_find_overridden_directionality,
25778 Sbidi_find_overridden_directionality, 3, 4, 0,
25779 doc:
25780
25781
25782
25783
25784
25785
25786
25787
25788
25789
25790
25791
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801
25802
25803
25804
25805
25806
25807
25808
25809
25810
25811
25812
25813
25814
25815
25816 )
25817 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25818 {
25819 struct buffer *buf = current_buffer;
25820 struct buffer *old = buf;
25821 struct window *w = NULL;
25822 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25823 struct bidi_it itb;
25824 ptrdiff_t from_pos, to_pos, from_bpos;
25825 void *itb_data;
25826
25827 if (!NILP (object))
25828 {
25829 if (BUFFERP (object))
25830 buf = XBUFFER (object);
25831 else if (WINDOWP (object))
25832 {
25833 w = decode_live_window (object);
25834 buf = XBUFFER (w->contents);
25835 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25836 }
25837 else
25838 CHECK_STRING (object);
25839 }
25840
25841 if (STRINGP (object))
25842 {
25843
25844
25845 if (!STRING_MULTIBYTE (object)
25846
25847
25848
25849 || redisplay__inhibit_bidi)
25850 return Qnil;
25851
25852 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25853 if (from_pos >= SCHARS (object))
25854 return Qnil;
25855
25856
25857 itb_data = bidi_shelve_cache ();
25858 itb.paragraph_dir = NEUTRAL_DIR;
25859 itb.string.lstring = object;
25860 itb.string.s = NULL;
25861 itb.string.schars = SCHARS (object);
25862 itb.string.bufpos = 0;
25863 itb.string.from_disp_str = false;
25864 itb.string.unibyte = false;
25865 itb.w = w;
25866 bidi_init_it (0, 0, frame_window_p, &itb);
25867 }
25868 else
25869 {
25870
25871
25872 if (NILP (BVAR (buf, bidi_display_reordering))
25873 || NILP (BVAR (buf, enable_multibyte_characters))
25874
25875
25876
25877 || redisplay__inhibit_bidi)
25878 return Qnil;
25879
25880 set_buffer_temp (buf);
25881 validate_region (&from, &to);
25882 from_pos = XFIXNUM (from);
25883 to_pos = XFIXNUM (to);
25884 if (from_pos >= ZV)
25885 return Qnil;
25886
25887
25888 itb_data = bidi_shelve_cache ();
25889 from_bpos = CHAR_TO_BYTE (from_pos);
25890 if (from_pos == BEGV)
25891 {
25892 itb.charpos = BEGV;
25893 itb.bytepos = BEGV_BYTE;
25894 }
25895 else if (FETCH_BYTE (from_bpos - 1) == '\n')
25896 {
25897 itb.charpos = from_pos;
25898 itb.bytepos = from_bpos;
25899 }
25900 else
25901 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
25902 -1, &itb.bytepos);
25903 itb.paragraph_dir = NEUTRAL_DIR;
25904 itb.string.s = NULL;
25905 itb.string.lstring = Qnil;
25906 itb.string.bufpos = 0;
25907 itb.string.from_disp_str = false;
25908 itb.string.unibyte = false;
25909 itb.w = w;
25910 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
25911 }
25912
25913 ptrdiff_t found;
25914 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
25915 do {
25916 bidi_paragraph_init (bdir, &itb, false);
25917 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
25918 ;
25919 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
25920
25921 bidi_unshelve_cache (itb_data, false);
25922 set_buffer_temp (old);
25923
25924 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
25925 }
25926
25927 DEFUN ("move-point-visually", Fmove_point_visually,
25928 Smove_point_visually, 1, 1, 0,
25929 doc:
25930
25931
25932
25933 )
25934 (Lisp_Object direction)
25935 {
25936 struct window *w = XWINDOW (selected_window);
25937 struct buffer *b = XBUFFER (w->contents);
25938 struct glyph_row *row;
25939 int dir;
25940 Lisp_Object paragraph_dir;
25941
25942 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
25943 (!(ROW)->continued_p \
25944 && NILP ((GLYPH)->object) \
25945 && (GLYPH)->type == CHAR_GLYPH \
25946 && (GLYPH)->u.ch == ' ' \
25947 && (GLYPH)->charpos >= 0 \
25948 && !(GLYPH)->avoid_cursor_p)
25949
25950 CHECK_FIXNUM (direction);
25951 dir = XFIXNUM (direction);
25952 if (dir > 0)
25953 dir = 1;
25954 else
25955 dir = -1;
25956
25957
25958
25959
25960 if (w->window_end_valid
25961 && !windows_or_buffers_changed
25962 && b
25963 && !b->clip_changed
25964 && !b->prevent_redisplay_optimizations_p
25965 && !window_outdated (w)
25966
25967
25968
25969 && w->last_point == BUF_PT (b)
25970 && w->cursor.vpos >= 0
25971 && w->cursor.vpos < w->current_matrix->nrows
25972 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
25973 {
25974 struct glyph *g = row->glyphs[TEXT_AREA];
25975 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
25976 struct glyph *gpt = g + w->cursor.hpos;
25977
25978 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
25979 {
25980 if (BUFFERP (g->object) && g->charpos != PT)
25981 {
25982 SET_PT (g->charpos);
25983 w->cursor.vpos = -1;
25984 return make_fixnum (PT);
25985 }
25986 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
25987 {
25988 ptrdiff_t new_pos;
25989
25990 if (BUFFERP (gpt->object))
25991 {
25992 new_pos = PT;
25993 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
25994 new_pos += (row->reversed_p ? -dir : dir);
25995 else
25996 new_pos -= (row->reversed_p ? -dir : dir);
25997 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
25998
25999
26000 if (new_pos == PT)
26001 break;
26002 }
26003 else if (BUFFERP (g->object))
26004 new_pos = g->charpos;
26005 else
26006 break;
26007 SET_PT (new_pos);
26008 w->cursor.vpos = -1;
26009 return make_fixnum (PT);
26010 }
26011 else if (ROW_GLYPH_NEWLINE_P (row, g))
26012 {
26013
26014
26015
26016 if (g->charpos > 0)
26017 SET_PT (g->charpos);
26018 else if (row->ends_at_zv_p && PT != ZV)
26019 SET_PT (ZV);
26020 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26021 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26022 else
26023 break;
26024 w->cursor.vpos = -1;
26025 return make_fixnum (PT);
26026 }
26027 }
26028 if (g == e || NILP (g->object))
26029 {
26030 if (row->truncated_on_left_p || row->truncated_on_right_p)
26031 goto simulate_display;
26032 if (!row->reversed_p)
26033 row += dir;
26034 else
26035 row -= dir;
26036 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26037 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26038 goto simulate_display;
26039
26040 if (dir > 0)
26041 {
26042 if (row->reversed_p && !row->continued_p)
26043 {
26044 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26045 w->cursor.vpos = -1;
26046 return make_fixnum (PT);
26047 }
26048 g = row->glyphs[TEXT_AREA];
26049 e = g + row->used[TEXT_AREA];
26050 for ( ; g < e; g++)
26051 {
26052 if (BUFFERP (g->object)
26053
26054
26055
26056 || ROW_GLYPH_NEWLINE_P (row, g)
26057
26058
26059 || (row->ends_at_zv_p
26060 && !row->reversed_p
26061 && NILP (g->object)
26062 && g->type == CHAR_GLYPH
26063 && g->u.ch == ' '))
26064 {
26065 if (g->charpos > 0)
26066 SET_PT (g->charpos);
26067 else if (!row->reversed_p
26068 && row->ends_at_zv_p
26069 && PT != ZV)
26070 SET_PT (ZV);
26071 else
26072 continue;
26073 w->cursor.vpos = -1;
26074 return make_fixnum (PT);
26075 }
26076 }
26077 }
26078 else
26079 {
26080 if (!row->reversed_p && !row->continued_p)
26081 {
26082 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26083 w->cursor.vpos = -1;
26084 return make_fixnum (PT);
26085 }
26086 e = row->glyphs[TEXT_AREA];
26087 g = e + row->used[TEXT_AREA] - 1;
26088 for ( ; g >= e; g--)
26089 {
26090 if (BUFFERP (g->object)
26091 || (ROW_GLYPH_NEWLINE_P (row, g)
26092 && g->charpos > 0)
26093
26094
26095
26096 || g->type == STRETCH_GLYPH
26097 || (row->ends_at_zv_p
26098 && row->reversed_p
26099 && NILP (g->object)
26100 && g->type == CHAR_GLYPH
26101 && g->u.ch == ' '))
26102 {
26103 if (g->charpos > 0)
26104 SET_PT (g->charpos);
26105 else if (row->reversed_p
26106 && row->ends_at_zv_p
26107 && PT != ZV)
26108 SET_PT (ZV);
26109 else
26110 continue;
26111 w->cursor.vpos = -1;
26112 return make_fixnum (PT);
26113 }
26114 }
26115 }
26116 }
26117 }
26118
26119 simulate_display:
26120
26121
26122
26123
26124 if (b)
26125 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26126 else
26127 paragraph_dir = Qleft_to_right;
26128 if (EQ (paragraph_dir, Qright_to_left))
26129 dir = -dir;
26130 if (PT <= BEGV && dir < 0)
26131 xsignal0 (Qbeginning_of_buffer);
26132 else if (PT >= ZV && dir > 0)
26133 xsignal0 (Qend_of_buffer);
26134 else
26135 {
26136 struct text_pos pt;
26137 struct it it;
26138 int pt_x, target_x, pixel_width, pt_vpos;
26139 bool at_eol_p;
26140 bool overshoot_expected = false;
26141 bool target_is_eol_p = false;
26142 void *itdata = bidi_shelve_cache ();
26143
26144
26145 SET_TEXT_POS (pt, PT, PT_BYTE);
26146 start_display (&it, w, pt);
26147
26148
26149
26150
26151
26152
26153 if (it.line_wrap == TRUNCATE)
26154 it.last_visible_x = DISP_INFINITY;
26155
26156 if (it.cmp_it.id < 0
26157 && it.method == GET_FROM_STRING
26158 && it.area == TEXT_AREA
26159 && it.string_from_display_prop_p
26160 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26161 overshoot_expected = true;
26162
26163
26164
26165
26166
26167 reseat:
26168 reseat_at_previous_visible_line_start (&it);
26169 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26170 if (IT_CHARPOS (it) != PT)
26171 {
26172 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26173 -1, -1, -1, MOVE_TO_POS);
26174
26175
26176
26177 if (it.method == GET_FROM_DISPLAY_VECTOR
26178 && it.current.dpvec_index > 0
26179 && !overshoot_expected)
26180 {
26181 overshoot_expected = true;
26182 goto reseat;
26183 }
26184 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26185 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26186 }
26187 pt_x = it.current_x;
26188 pt_vpos = it.vpos;
26189 if (dir > 0 || overshoot_expected)
26190 {
26191 struct glyph_row *row = it.glyph_row;
26192
26193
26194
26195
26196 if (pt_x == 0)
26197 get_next_display_element (&it);
26198 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26199 it.glyph_row = NULL;
26200 PRODUCE_GLYPHS (&it);
26201 it.glyph_row = row;
26202
26203
26204
26205 it.current_x = pt_x;
26206 }
26207 else
26208 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26209 pixel_width = it.pixel_width;
26210 if (overshoot_expected && at_eol_p)
26211 pixel_width = 0;
26212 else if (pixel_width <= 0)
26213 pixel_width = 1;
26214
26215
26216
26217
26218 if (overshoot_expected)
26219 {
26220 if (it.bidi_p)
26221 pt_x += pixel_width * it.bidi_it.scan_dir;
26222 else
26223 pt_x += pixel_width;
26224 }
26225
26226
26227
26228
26229
26230
26231
26232 if (dir > 0)
26233 target_x = pt_x + pixel_width;
26234 else
26235 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26236
26237
26238
26239
26240
26241 if (dir < 0)
26242 {
26243 if (pt_x > 0)
26244 {
26245 start_display (&it, w, pt);
26246 if (it.line_wrap == TRUNCATE)
26247 it.last_visible_x = DISP_INFINITY;
26248 reseat_at_previous_visible_line_start (&it);
26249 it.current_x = it.current_y = it.hpos = 0;
26250 if (pt_vpos != 0)
26251 move_it_by_lines (&it, pt_vpos);
26252 }
26253 else
26254 {
26255 move_it_by_lines (&it, -1);
26256 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26257 target_is_eol_p = true;
26258
26259
26260
26261
26262
26263
26264
26265
26266
26267
26268 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26269 {
26270 void *it_data = NULL;
26271 struct it it2;
26272
26273 SAVE_IT (it2, it, it_data);
26274 move_it_in_display_line_to (&it, ZV, target_x,
26275 MOVE_TO_POS | MOVE_TO_X);
26276
26277
26278 if (it.current_x != target_x)
26279 target_x = it.current_x - 1;
26280 RESTORE_IT (&it, &it2, it_data);
26281 }
26282 }
26283 }
26284 else
26285 {
26286 if (at_eol_p
26287 || (target_x >= it.last_visible_x
26288 && it.line_wrap != TRUNCATE))
26289 {
26290 if (pt_x > 0)
26291 move_it_by_lines (&it, 0);
26292 move_it_by_lines (&it, 1);
26293 target_x = 0;
26294 }
26295 }
26296
26297
26298
26299
26300
26301
26302
26303 if (FRAME_WINDOW_P (it.f) && dir < 0)
26304 {
26305 struct text_pos new_pos;
26306 enum move_it_result rc = MOVE_X_REACHED;
26307
26308 if (it.current_x == 0)
26309 get_next_display_element (&it);
26310 if (it.what == IT_COMPOSITION)
26311 {
26312 new_pos.charpos = it.cmp_it.charpos;
26313 new_pos.bytepos = -1;
26314 }
26315 else
26316 new_pos = it.current.pos;
26317
26318 while (it.current_x + it.pixel_width <= target_x
26319 && (rc == MOVE_X_REACHED
26320
26321
26322
26323 || (it.line_wrap == WORD_WRAP
26324 && rc == MOVE_POS_MATCH_OR_ZV)))
26325 {
26326 int new_x = it.current_x + it.pixel_width;
26327
26328
26329
26330
26331
26332
26333
26334 if (it.what == IT_COMPOSITION)
26335 {
26336 new_pos.charpos = it.cmp_it.charpos;
26337 new_pos.bytepos = -1;
26338 }
26339 else
26340 new_pos = it.current.pos;
26341 if (new_x == it.current_x)
26342 new_x++;
26343 rc = move_it_in_display_line_to (&it, ZV, new_x,
26344 MOVE_TO_POS | MOVE_TO_X);
26345 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26346 break;
26347 }
26348
26349
26350 if (new_pos.bytepos == -1)
26351 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26352 it.current.pos = new_pos;
26353 }
26354 else if (it.current_x != target_x)
26355 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26356
26357
26358
26359 if (dir > 0)
26360 {
26361 while (IT_CHARPOS (it) == PT)
26362 {
26363 set_iterator_to_next (&it, false);
26364 if (!get_next_display_element (&it))
26365 break;
26366 }
26367 }
26368
26369
26370 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26371 bidi_unshelve_cache (itdata, false);
26372 }
26373
26374 return make_fixnum (PT);
26375
26376 #undef ROW_GLYPH_NEWLINE_P
26377 }
26378
26379 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26380 Sbidi_resolved_levels, 0, 1, 0,
26381 doc:
26382
26383
26384
26385
26386
26387
26388
26389
26390
26391
26392
26393
26394
26395
26396
26397
26398
26399
26400
26401
26402
26403
26404
26405
26406
26407 )
26408 (Lisp_Object vpos)
26409 {
26410 struct window *w = XWINDOW (selected_window);
26411 struct buffer *b = XBUFFER (w->contents);
26412 int nrow;
26413 struct glyph_row *row;
26414
26415 if (NILP (vpos))
26416 {
26417 int d1, d2, d3, d4, d5;
26418
26419 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26420 }
26421 else
26422 {
26423 CHECK_FIXNUM (vpos);
26424 nrow = XFIXNUM (vpos);
26425 }
26426
26427
26428 if (w->window_end_valid
26429 && !windows_or_buffers_changed
26430 && b
26431 && !b->clip_changed
26432 && !b->prevent_redisplay_optimizations_p
26433 && !window_outdated (w)
26434 && nrow >= 0
26435 && nrow < w->current_matrix->nrows
26436 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26437 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26438 {
26439 struct glyph *g, *e, *g1;
26440 int nglyphs, i;
26441 Lisp_Object levels;
26442
26443 if (!row->reversed_p)
26444 {
26445 g = g1 = row->glyphs[TEXT_AREA];
26446 e = g + row->used[TEXT_AREA];
26447
26448
26449
26450 while (g < e
26451 && NILP (g->object)
26452 && g->charpos < 0)
26453 g++;
26454 g1 = g;
26455
26456
26457 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26458 nglyphs++;
26459
26460
26461 levels = make_uninit_vector (nglyphs);
26462 for (i = 0; g1 < g; i++, g1++)
26463 ASET (levels, i, make_fixnum (g1->resolved_level));
26464 }
26465 else
26466 {
26467 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26468 e = row->glyphs[TEXT_AREA] - 1;
26469 while (g > e
26470 && NILP (g->object)
26471 && g->charpos < 0)
26472 g--;
26473 g1 = g;
26474 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26475 nglyphs++;
26476 levels = make_uninit_vector (nglyphs);
26477 for (i = 0; g1 > g; i++, g1--)
26478 ASET (levels, i, make_fixnum (g1->resolved_level));
26479 }
26480 return levels;
26481 }
26482 else
26483 return Qnil;
26484 }
26485
26486
26487
26488
26489
26490
26491
26492
26493
26494
26495
26496
26497
26498
26499
26500
26501
26502 static void
26503 display_menu_bar (struct window *w)
26504 {
26505 struct frame *f = XFRAME (WINDOW_FRAME (w));
26506 struct it it;
26507 Lisp_Object items;
26508 int i;
26509
26510
26511 #ifdef HAVE_NTGUI
26512 if (FRAME_W32_P (f))
26513 return;
26514 #endif
26515 #if defined (HAVE_PGTK)
26516 if (FRAME_PGTK_P (f))
26517 return;
26518 #endif
26519
26520 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26521 if (FRAME_X_P (f))
26522 return;
26523 #endif
26524
26525 #ifdef HAVE_NS
26526 if (FRAME_NS_P (f))
26527 return;
26528 #endif
26529
26530 #ifdef HAVE_HAIKU
26531 if (FRAME_HAIKU_P (f))
26532 return;
26533 #endif
26534
26535 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26536 eassert (!FRAME_WINDOW_P (f));
26537 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26538 it.first_visible_x = 0;
26539 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26540 #elif defined (HAVE_X_WINDOWS)
26541 struct window *menu_window = NULL;
26542 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26543
26544 if (FRAME_WINDOW_P (f))
26545 {
26546
26547
26548 menu_window = XWINDOW (f->menu_bar_window);
26549 init_iterator (&it, menu_window, -1, -1,
26550 menu_window->desired_matrix->rows,
26551 MENU_FACE_ID);
26552 }
26553 else
26554 #endif
26555 {
26556
26557
26558 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26559 MENU_FACE_ID);
26560 it.first_visible_x = 0;
26561 it.last_visible_x = FRAME_COLS (f);
26562 }
26563
26564
26565
26566
26567 it.paragraph_embedding = L2R;
26568
26569
26570 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26571 {
26572 struct glyph_row *row = it.glyph_row + i;
26573 clear_glyph_row (row);
26574 row->enabled_p = true;
26575 row->full_width_p = true;
26576 row->reversed_p = false;
26577 }
26578
26579
26580 items = FRAME_MENU_BAR_ITEMS (it.f);
26581 for (i = 0; i < ASIZE (items); i += 4)
26582 {
26583 Lisp_Object string;
26584
26585
26586 string = AREF (items, i + 1);
26587 if (NILP (string))
26588 break;
26589
26590
26591 ASET (items, i + 3, make_fixnum (it.hpos));
26592
26593
26594 if (it.current_x < it.last_visible_x)
26595 display_string (NULL, string, Qnil, 0, 0, &it,
26596 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26597 }
26598
26599
26600 if (it.current_x < it.last_visible_x)
26601 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26602
26603
26604 compute_line_metrics (&it);
26605 it.glyph_row->full_width_p = true;
26606 it.glyph_row->continued_p = false;
26607 it.glyph_row->truncated_on_left_p = false;
26608 it.glyph_row->truncated_on_right_p = false;
26609
26610 #if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
26611
26612 extend_face_to_end_of_line (&it);
26613 if (face->box != FACE_NO_BOX)
26614 {
26615 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26616 + it.glyph_row->used[TEXT_AREA] - 1);
26617 int box_thickness = face->box_vertical_line_width;
26618 last->right_box_line_p = true;
26619
26620
26621
26622
26623
26624
26625 if (box_thickness > 0)
26626 last->pixel_width += max (0, (box_thickness
26627 - (it.current_x - it.last_visible_x)));
26628 }
26629
26630
26631
26632 if (FRAME_WINDOW_P (it.f) && menu_window)
26633 {
26634 struct glyph_row *row;
26635 int delta_height;
26636
26637 row = it.glyph_row;
26638 delta_height
26639 = ((row->y + row->height)
26640 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26641
26642 if (delta_height != 0)
26643 {
26644 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26645 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26646 }
26647 }
26648 #endif
26649 }
26650
26651
26652 static void
26653 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26654 {
26655 struct glyph *pointers[1 + LAST_AREA];
26656 int to_used = to->used[TEXT_AREA];
26657
26658
26659 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26660
26661
26662 *to = *from;
26663
26664
26665 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26666
26667
26668 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26669 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26670
26671
26672
26673 if (to_used > from->used[TEXT_AREA])
26674 fill_up_frame_row_with_spaces (to, to_used);
26675 }
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696
26697
26698 void
26699 display_tty_menu_item (const char *item_text, int width, int face_id,
26700 int x, int y, bool submenu)
26701 {
26702 struct it it;
26703 struct frame *f = SELECTED_FRAME ();
26704 struct window *w = XWINDOW (f->selected_window);
26705 struct glyph_row *row;
26706 size_t item_len = strlen (item_text);
26707
26708 eassert (FRAME_TERMCAP_P (f));
26709
26710
26711
26712
26713
26714
26715 if (y >= f->desired_matrix->nrows)
26716 return;
26717
26718 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26719 it.first_visible_x = 0;
26720 it.last_visible_x = FRAME_COLS (f) - 1;
26721 row = it.glyph_row;
26722
26723 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26724 bool saved_width = row->full_width_p;
26725 row->full_width_p = true;
26726 bool saved_reversed = row->reversed_p;
26727 row->reversed_p = false;
26728 row->enabled_p = true;
26729
26730
26731
26732 eassert (x < f->desired_matrix->matrix_w);
26733 it.current_x = it.hpos = x;
26734 it.current_y = it.vpos = y;
26735 int saved_used = row->used[TEXT_AREA];
26736 bool saved_truncated = row->truncated_on_right_p;
26737 row->used[TEXT_AREA] = x;
26738 it.face_id = face_id;
26739 it.line_wrap = TRUNCATE;
26740
26741
26742
26743
26744
26745
26746 it.paragraph_embedding = L2R;
26747
26748
26749 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26750 width--;
26751
26752 if (submenu)
26753 {
26754 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26755 item_len, 0, FRAME_COLS (f) - 1, -1);
26756 width -= item_len;
26757
26758 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26759 FRAME_COLS (f) - 1, -1);
26760 }
26761 else
26762 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26763 width, 0, FRAME_COLS (f) - 1, -1);
26764
26765 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26766 row->truncated_on_right_p = saved_truncated;
26767 row->hash = row_hash (row);
26768 row->full_width_p = saved_width;
26769 row->reversed_p = saved_reversed;
26770 }
26771
26772
26773
26774
26775
26776
26777
26778
26779
26780
26781 static int
26782 redisplay_mode_lines (Lisp_Object window, bool force)
26783 {
26784 int nwindows = 0;
26785
26786 while (!NILP (window))
26787 {
26788 struct window *w = XWINDOW (window);
26789
26790 if (WINDOWP (w->contents))
26791 nwindows += redisplay_mode_lines (w->contents, force);
26792 else if (force
26793 || FRAME_GARBAGED_P (XFRAME (w->frame))
26794 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26795 {
26796 struct text_pos lpoint;
26797 struct buffer *old = current_buffer;
26798
26799
26800 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26801 set_buffer_internal_1 (XBUFFER (w->contents));
26802
26803
26804
26805 if (!EQ (window, selected_window))
26806 {
26807 struct text_pos pt;
26808
26809 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26810 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26811 }
26812
26813
26814 clear_glyph_matrix (w->desired_matrix);
26815 if (display_mode_lines (w))
26816 ++nwindows;
26817
26818
26819 set_buffer_internal_1 (old);
26820 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26821 }
26822
26823 window = w->next;
26824 }
26825
26826 return nwindows;
26827 }
26828
26829
26830
26831
26832
26833
26834 static int
26835 display_mode_lines (struct window *w)
26836 {
26837 Lisp_Object old_selected_window = selected_window;
26838 Lisp_Object new_frame = w->frame;
26839 specpdl_ref count = SPECPDL_INDEX ();
26840 int n = 0;
26841
26842 record_unwind_protect (restore_selected_window, selected_window);
26843 record_unwind_protect
26844 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26845
26846 if (window_wants_mode_line (w))
26847 {
26848 Lisp_Object window;
26849 Lisp_Object default_help
26850 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26851
26852
26853
26854 XSETWINDOW (window, w);
26855 if (FUNCTIONP (default_help))
26856 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26857 else if (STRINGP (default_help))
26858 wset_mode_line_help_echo (w, default_help);
26859 else
26860 wset_mode_line_help_echo (w, Qnil);
26861 }
26862
26863 selected_frame = new_frame;
26864
26865
26866 XSETWINDOW (selected_window, w);
26867 XFRAME (new_frame)->selected_window = selected_window;
26868
26869
26870 line_number_displayed = false;
26871 w->column_number_displayed = -1;
26872
26873 if (window_wants_mode_line (w))
26874 {
26875 Lisp_Object window_mode_line_format
26876 = window_parameter (w, Qmode_line_format);
26877 struct window *sel_w = XWINDOW (old_selected_window);
26878
26879
26880 display_mode_line (w,
26881 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
26882 NILP (window_mode_line_format)
26883 ? BVAR (current_buffer, mode_line_format)
26884 : window_mode_line_format);
26885 ++n;
26886 }
26887
26888 if (window_wants_tab_line (w))
26889 {
26890 Lisp_Object window_tab_line_format
26891 = window_parameter (w, Qtab_line_format);
26892
26893 display_mode_line (w, TAB_LINE_FACE_ID,
26894 NILP (window_tab_line_format)
26895 ? BVAR (current_buffer, tab_line_format)
26896 : window_tab_line_format);
26897 ++n;
26898 }
26899
26900 if (window_wants_header_line (w))
26901 {
26902 Lisp_Object window_header_line_format
26903 = window_parameter (w, Qheader_line_format);
26904
26905 display_mode_line (w, HEADER_LINE_FACE_ID,
26906 NILP (window_header_line_format)
26907 ? BVAR (current_buffer, header_line_format)
26908 : window_header_line_format);
26909 ++n;
26910 }
26911
26912 unbind_to (count, Qnil);
26913
26914 if (n > 0)
26915 w->must_be_updated_p = true;
26916 return n;
26917 }
26918
26919
26920
26921
26922
26923
26924
26925
26926 static int
26927 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26928 {
26929 struct it it;
26930 struct face *face;
26931 specpdl_ref count = SPECPDL_INDEX ();
26932
26933 init_iterator (&it, w, -1, -1, NULL, face_id);
26934
26935
26936 it.glyph_row->enabled_p = false;
26937 prepare_desired_row (w, it.glyph_row, true);
26938
26939 it.glyph_row->mode_line_p = true;
26940 if (face_id == TAB_LINE_FACE_ID)
26941 {
26942 it.glyph_row->tab_line_p = true;
26943 w->desired_matrix->tab_line_p = true;
26944 }
26945 else if (face_id == HEADER_LINE_FACE_ID)
26946 w->desired_matrix->header_line_p = true;
26947
26948
26949
26950
26951 it.paragraph_embedding = L2R;
26952
26953 record_unwind_protect (unwind_format_mode_line,
26954 format_mode_line_unwind_data (NULL, NULL,
26955 Qnil, false));
26956
26957
26958
26959
26960 push_kboard (FRAME_KBOARD (it.f));
26961 record_unwind_save_match_data ();
26962
26963 if (NILP (Vmode_line_compact)
26964 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
26965 {
26966 mode_line_target = MODE_LINE_DISPLAY;
26967 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
26968 }
26969 else
26970 {
26971 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
26972 if (EQ (Vmode_line_compact, Qlong)
26973 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
26974 {
26975
26976
26977 display_string (NULL, mode_string, Qnil,
26978 0, 0, &it, 0, 0, 0,
26979 STRING_MULTIBYTE (mode_string));
26980 }
26981 else
26982 {
26983
26984 ptrdiff_t i = 0, i_byte = 0, start = 0;
26985 int prev = 0;
26986
26987 while (i < SCHARS (mode_string))
26988 {
26989 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
26990 if (c == ' ' && prev == ' ')
26991 {
26992 display_string (NULL,
26993 Fsubstring (mode_string, make_fixnum (start),
26994 make_fixnum (i - 1)),
26995 Qnil, 0, 0, &it, 0, 0, 0,
26996 STRING_MULTIBYTE (mode_string));
26997
26998 while (c == ' ' && i < SCHARS (mode_string))
26999 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27000 start = i - 1;
27001 }
27002 prev = c;
27003 }
27004
27005
27006 if (start < i)
27007 display_string (NULL,
27008 Fsubstring (mode_string, make_fixnum (start),
27009 make_fixnum (i)),
27010 Qnil, 0, 0, &it, 0, 0, 0,
27011 STRING_MULTIBYTE (mode_string));
27012 }
27013 }
27014 pop_kboard ();
27015
27016 unbind_to (count, Qnil);
27017
27018
27019 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27020
27021 compute_line_metrics (&it);
27022 it.glyph_row->full_width_p = true;
27023 it.glyph_row->continued_p = false;
27024 it.glyph_row->truncated_on_left_p = false;
27025 it.glyph_row->truncated_on_right_p = false;
27026
27027
27028 face = FACE_FROM_ID (it.f, face_id);
27029 extend_face_to_end_of_line (&it);
27030 if (face->box != FACE_NO_BOX)
27031 {
27032 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27033 + it.glyph_row->used[TEXT_AREA] - 1);
27034 int box_thickness = face->box_vertical_line_width;
27035 last->right_box_line_p = true;
27036
27037
27038
27039
27040
27041
27042 if (box_thickness > 0)
27043 last->pixel_width += max (0, (box_thickness
27044 - (it.current_x - it.last_visible_x)));
27045 }
27046
27047 return it.glyph_row->height;
27048 }
27049
27050
27051
27052
27053 static Lisp_Object
27054 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27055 {
27056 register Lisp_Object tail, prev;
27057 register Lisp_Object tem;
27058
27059 tail = list;
27060 prev = Qnil;
27061 while (CONSP (tail))
27062 {
27063 tem = XCAR (tail);
27064
27065 if (EQ (elt, tem))
27066 {
27067
27068 if (NILP (prev))
27069 list = XCDR (tail);
27070 else
27071 Fsetcdr (prev, XCDR (tail));
27072
27073
27074 Fsetcdr (tail, list);
27075 return tail;
27076 }
27077 else
27078 prev = tail;
27079 tail = XCDR (tail);
27080 maybe_quit ();
27081 }
27082
27083
27084 return list;
27085 }
27086
27087
27088
27089
27090
27091 static Lisp_Object
27092 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27093 {
27094 eassert (nargs == 4);
27095 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27096 }
27097
27098
27099
27100
27101
27102
27103
27104
27105
27106
27107
27108
27109
27110
27111
27112
27113
27114
27115
27116
27117
27118
27119
27120
27121
27122 static int
27123 display_mode_element (struct it *it, int depth, int field_width, int precision,
27124 Lisp_Object elt, Lisp_Object props, bool risky)
27125 {
27126 int n = 0, field, prec;
27127 bool literal = false;
27128
27129 tail_recurse:
27130 if (depth > 100)
27131 elt = build_string ("*too-deep*");
27132
27133 depth++;
27134
27135 switch (XTYPE (elt))
27136 {
27137 case Lisp_String:
27138 {
27139
27140 unsigned char c;
27141 ptrdiff_t offset = 0;
27142
27143 if (SCHARS (elt) > 0
27144 && (!NILP (props) || risky))
27145 {
27146 Lisp_Object oprops, aelt;
27147 oprops = Ftext_properties_at (make_fixnum (0), elt);
27148
27149
27150
27151
27152
27153 if (NILP (Fequal (props, oprops)) || risky)
27154 {
27155
27156
27157 if (! NILP (oprops) && !risky)
27158 {
27159 Lisp_Object tem;
27160
27161 oprops = Fcopy_sequence (oprops);
27162 tem = props;
27163 while (CONSP (tem))
27164 {
27165 oprops = plist_put (oprops, XCAR (tem),
27166 XCAR (XCDR (tem)));
27167 tem = XCDR (XCDR (tem));
27168 }
27169 props = oprops;
27170 }
27171
27172 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27173 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27174 {
27175
27176
27177 elt = XCAR (aelt);
27178 mode_line_proptrans_alist
27179 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27180 }
27181 else
27182 {
27183 Lisp_Object tem;
27184
27185
27186
27187 if (! NILP (aelt))
27188 mode_line_proptrans_alist
27189 = Fdelq (aelt, mode_line_proptrans_alist);
27190
27191 elt = Fcopy_sequence (elt);
27192
27193
27194
27195 internal_condition_case_n (safe_set_text_properties,
27196 4,
27197 ((Lisp_Object [])
27198 {make_fixnum (0),
27199 Flength (elt),
27200 props,
27201 elt}),
27202 Qt, safe_eval_handler);
27203
27204 mode_line_proptrans_alist
27205 = Fcons (Fcons (elt, props),
27206 mode_line_proptrans_alist);
27207
27208
27209 tem = Fnthcdr (make_fixnum (50),
27210 mode_line_proptrans_alist);
27211 if (! NILP (tem))
27212 XSETCDR (tem, Qnil);
27213 }
27214 }
27215 }
27216
27217 offset = 0;
27218
27219 if (literal)
27220 {
27221 prec = precision - n;
27222 switch (mode_line_target)
27223 {
27224 case MODE_LINE_NOPROP:
27225 case MODE_LINE_TITLE:
27226 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27227 break;
27228 case MODE_LINE_STRING:
27229 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27230 break;
27231 case MODE_LINE_DISPLAY:
27232 n += display_string (NULL, elt, Qnil, 0, 0, it,
27233 0, prec, 0, STRING_MULTIBYTE (elt));
27234 break;
27235 }
27236
27237 break;
27238 }
27239
27240
27241
27242 while ((precision <= 0 || n < precision)
27243 && SREF (elt, offset) != 0
27244 && (mode_line_target != MODE_LINE_DISPLAY
27245 || it->current_x < it->last_visible_x))
27246 {
27247 ptrdiff_t last_offset = offset;
27248
27249
27250 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27251 ;
27252
27253 if (offset - 1 != last_offset)
27254 {
27255 ptrdiff_t nchars, nbytes;
27256
27257
27258
27259
27260 offset--;
27261
27262 prec = c_string_width (SDATA (elt) + last_offset,
27263 offset - last_offset, precision - n,
27264 &nchars, &nbytes);
27265
27266 switch (mode_line_target)
27267 {
27268 case MODE_LINE_NOPROP:
27269 case MODE_LINE_TITLE:
27270 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27271 break;
27272 case MODE_LINE_STRING:
27273 {
27274 ptrdiff_t bytepos = last_offset;
27275 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27276 ptrdiff_t endpos = (precision <= 0
27277 ? string_byte_to_char (elt, offset)
27278 : charpos + nchars);
27279 Lisp_Object mode_string
27280 = Fsubstring (elt, make_fixnum (charpos),
27281 make_fixnum (endpos));
27282 n += store_mode_line_string (NULL, mode_string, false,
27283 0, 0, Qnil);
27284 }
27285 break;
27286 case MODE_LINE_DISPLAY:
27287 {
27288 ptrdiff_t bytepos = last_offset;
27289 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27290
27291 if (precision <= 0)
27292 nchars = string_byte_to_char (elt, offset) - charpos;
27293 n += display_string (NULL, elt, Qnil, 0, charpos,
27294 it, 0, nchars, 0,
27295 STRING_MULTIBYTE (elt));
27296 }
27297 break;
27298 }
27299 }
27300 else
27301 {
27302 ptrdiff_t percent_position = offset;
27303
27304
27305
27306 field = 0;
27307 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27308 field = field * 10 + c - '0';
27309
27310
27311 if (field_width - n > 0 && field > field_width - n)
27312 field = field_width - n;
27313
27314
27315 prec = precision - n;
27316
27317 if (c == 'M')
27318 n += display_mode_element (it, depth, field, prec,
27319 Vglobal_mode_string, props,
27320 risky);
27321 else if (c != 0)
27322 {
27323 bool multibyte;
27324 ptrdiff_t bytepos, charpos;
27325 const char *spec;
27326 Lisp_Object string;
27327
27328 bytepos = percent_position;
27329 charpos = (STRING_MULTIBYTE (elt)
27330 ? string_byte_to_char (elt, bytepos)
27331 : bytepos);
27332 spec = decode_mode_spec (it->w, c, field, &string);
27333 eassert (NILP (string) || STRINGP (string));
27334 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27335
27336
27337 ptrdiff_t nbytes = strlen (spec);
27338 ptrdiff_t nchars, mb_nbytes;
27339 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27340 &nchars, &mb_nbytes);
27341 if (!(nbytes == nchars || nbytes != mb_nbytes))
27342 multibyte = true;
27343
27344 switch (mode_line_target)
27345 {
27346 case MODE_LINE_NOPROP:
27347 case MODE_LINE_TITLE:
27348 n += store_mode_line_noprop (spec, field, prec);
27349 break;
27350 case MODE_LINE_STRING:
27351 {
27352 Lisp_Object tem = build_string (spec);
27353 props = Ftext_properties_at (make_fixnum (charpos), elt);
27354
27355 n += store_mode_line_string (NULL, tem, false,
27356 field, prec, props);
27357 }
27358 break;
27359 case MODE_LINE_DISPLAY:
27360 {
27361 int nglyphs_before, nwritten;
27362
27363 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27364 nwritten = display_string (spec, string, elt,
27365 charpos, 0, it,
27366 field, prec, 0,
27367 multibyte);
27368
27369
27370
27371
27372 if (nwritten > 0)
27373 {
27374 struct glyph *glyph
27375 = (it->glyph_row->glyphs[TEXT_AREA]
27376 + nglyphs_before);
27377 int i;
27378
27379 for (i = 0; i < nwritten; ++i)
27380 {
27381 glyph[i].object = elt;
27382 glyph[i].charpos = charpos;
27383 }
27384
27385 n += nwritten;
27386 }
27387 }
27388 break;
27389 }
27390 }
27391 else
27392 break;
27393 }
27394 }
27395 }
27396 break;
27397
27398 case Lisp_Symbol:
27399
27400
27401
27402
27403 {
27404 register Lisp_Object tem;
27405
27406
27407
27408 if (NILP (Fget (elt, Qrisky_local_variable)))
27409 risky = true;
27410
27411 tem = Fboundp (elt);
27412 if (!NILP (tem))
27413 {
27414 tem = Fsymbol_value (elt);
27415
27416
27417 if (STRINGP (tem))
27418 literal = true;
27419
27420 if (!EQ (tem, elt))
27421 {
27422
27423 elt = tem;
27424 goto tail_recurse;
27425 }
27426 }
27427 }
27428 break;
27429
27430 case Lisp_Cons:
27431 {
27432 register Lisp_Object car, tem;
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442
27443 car = XCAR (elt);
27444 if (EQ (car, QCeval))
27445 {
27446
27447
27448
27449 if (risky)
27450 break;
27451
27452 if (CONSP (XCDR (elt)))
27453 {
27454 Lisp_Object spec;
27455 spec = safe__eval (true, XCAR (XCDR (elt)));
27456
27457
27458
27459
27460
27461
27462 if (!FRAME_LIVE_P (it->f))
27463 signal_error (":eval deleted the frame being displayed", elt);
27464 n += display_mode_element (it, depth, field_width - n,
27465 precision - n, spec, props,
27466 risky);
27467 }
27468 }
27469 else if (EQ (car, QCpropertize))
27470 {
27471
27472
27473
27474 if (risky)
27475 break;
27476
27477 if (CONSP (XCDR (elt)))
27478 n += display_mode_element (it, depth, field_width - n,
27479 precision - n, XCAR (XCDR (elt)),
27480 XCDR (XCDR (elt)), risky);
27481 }
27482 else if (SYMBOLP (car))
27483 {
27484 tem = Fboundp (car);
27485 elt = XCDR (elt);
27486 if (!CONSP (elt))
27487 goto invalid;
27488
27489
27490 if (!NILP (tem))
27491 {
27492 tem = Fsymbol_value (car);
27493 if (!NILP (tem))
27494 {
27495 elt = XCAR (elt);
27496 goto tail_recurse;
27497 }
27498 }
27499
27500
27501
27502 elt = XCDR (elt);
27503 if (NILP (elt))
27504 break;
27505 else if (!CONSP (elt))
27506 goto invalid;
27507 elt = XCAR (elt);
27508 goto tail_recurse;
27509 }
27510 else if (FIXNUMP (car))
27511 {
27512 register int lim = XFIXNUM (car);
27513 elt = XCDR (elt);
27514 if (lim < 0)
27515 {
27516
27517 if (precision <= 0)
27518 precision = -lim;
27519 else
27520 precision = min (precision, -lim);
27521 }
27522 else if (lim > 0)
27523 {
27524
27525
27526 if (precision > 0)
27527 lim = min (precision, lim);
27528
27529
27530
27531
27532 field_width = max (lim, field_width);
27533 }
27534 goto tail_recurse;
27535 }
27536 else if (STRINGP (car) || CONSP (car))
27537 FOR_EACH_TAIL_SAFE (elt)
27538 {
27539 if (0 < precision && precision <= n)
27540 break;
27541 n += display_mode_element (it, depth,
27542
27543
27544 (! CONSP (XCDR (elt))
27545 ? field_width - n
27546 : 0),
27547 precision - n, XCAR (elt),
27548 props, risky);
27549 }
27550 }
27551 break;
27552
27553 default:
27554 invalid:
27555 elt = build_string ("*invalid*");
27556 goto tail_recurse;
27557 }
27558
27559
27560 if (field_width > 0 && n < field_width)
27561 {
27562 switch (mode_line_target)
27563 {
27564 case MODE_LINE_NOPROP:
27565 case MODE_LINE_TITLE:
27566 n += store_mode_line_noprop ("", field_width - n, 0);
27567 break;
27568 case MODE_LINE_STRING:
27569 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27570 Qnil);
27571 break;
27572 case MODE_LINE_DISPLAY:
27573 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27574 0, 0, 0);
27575 break;
27576 }
27577 }
27578
27579 return n;
27580 }
27581
27582
27583
27584
27585
27586
27587
27588
27589
27590
27591
27592
27593
27594
27595
27596
27597
27598
27599
27600
27601 static int
27602 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27603 bool copy_string,
27604 int field_width, int precision, Lisp_Object props)
27605 {
27606 ptrdiff_t len;
27607 int n = 0;
27608
27609 if (string != NULL)
27610 {
27611 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27612 lisp_string = make_string (string, len);
27613 if (NILP (props))
27614 props = mode_line_string_face_prop;
27615 else if (!NILP (mode_line_string_face))
27616 {
27617 Lisp_Object face = plist_get (props, Qface);
27618 props = Fcopy_sequence (props);
27619 if (NILP (face))
27620 face = mode_line_string_face;
27621 else
27622 face = list2 (face, mode_line_string_face);
27623 props = plist_put (props, Qface, face);
27624 }
27625 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27626 props, lisp_string);
27627 }
27628 else
27629 {
27630 len = SCHARS (lisp_string);
27631 if (precision > 0 && len > precision)
27632 {
27633 len = precision;
27634 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27635 precision = -1;
27636 }
27637 if (!NILP (mode_line_string_face))
27638 {
27639 Lisp_Object face;
27640 if (NILP (props))
27641 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27642 face = plist_get (props, Qface);
27643 if (NILP (face))
27644 face = mode_line_string_face;
27645 else
27646 face = list2 (face, mode_line_string_face);
27647 props = list2 (Qface, face);
27648 if (copy_string)
27649 lisp_string = Fcopy_sequence (lisp_string);
27650 }
27651 if (!NILP (props))
27652 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27653 props, lisp_string);
27654 }
27655
27656 if (len > 0)
27657 {
27658 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27659 n += len;
27660 }
27661
27662 if (field_width > len)
27663 {
27664 field_width -= len;
27665 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27666 Qnil);
27667 if (!NILP (props))
27668 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27669 props, lisp_string);
27670 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27671 n += field_width;
27672 }
27673
27674 return n;
27675 }
27676
27677
27678 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27679 1, 4, 0,
27680 doc:
27681
27682
27683
27684
27685
27686
27687
27688
27689
27690
27691
27692
27693
27694
27695
27696 )
27697 (Lisp_Object format, Lisp_Object face,
27698 Lisp_Object window, Lisp_Object buffer)
27699 {
27700 struct it it;
27701 int len;
27702 struct window *w;
27703 struct buffer *old_buffer = NULL;
27704 int face_id;
27705 bool no_props = FIXNUMP (face);
27706 specpdl_ref count = SPECPDL_INDEX ();
27707 Lisp_Object str;
27708 int string_start = 0;
27709
27710 w = decode_any_window (window);
27711 XSETWINDOW (window, w);
27712
27713 if (NILP (buffer))
27714 buffer = w->contents;
27715 CHECK_BUFFER (buffer);
27716
27717
27718
27719 if (NILP (format) || noninteractive)
27720 return empty_unibyte_string;
27721
27722 if (no_props)
27723 face = Qnil;
27724
27725 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27726 : EQ (face, Qt) ? (EQ (window, selected_window)
27727 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27728 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27729 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27730 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27731 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27732 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27733 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27734 : DEFAULT_FACE_ID;
27735
27736 old_buffer = current_buffer;
27737
27738
27739
27740 record_unwind_protect (unwind_format_mode_line,
27741 format_mode_line_unwind_data
27742 (XFRAME (WINDOW_FRAME (w)),
27743 old_buffer, selected_window, true));
27744 mode_line_proptrans_alist = Qnil;
27745
27746 Fselect_window (window, Qt);
27747 set_buffer_internal_1 (XBUFFER (buffer));
27748
27749 init_iterator (&it, w, -1, -1, NULL, face_id);
27750
27751 if (no_props)
27752 {
27753 mode_line_target = MODE_LINE_NOPROP;
27754 mode_line_string_face_prop = Qnil;
27755 mode_line_string_list = Qnil;
27756 string_start = MODE_LINE_NOPROP_LEN (0);
27757 }
27758 else
27759 {
27760 mode_line_target = MODE_LINE_STRING;
27761 mode_line_string_list = Qnil;
27762 mode_line_string_face = face;
27763 mode_line_string_face_prop
27764 = NILP (face) ? Qnil : list2 (Qface, face);
27765 }
27766
27767 push_kboard (FRAME_KBOARD (it.f));
27768 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27769 pop_kboard ();
27770
27771 if (no_props)
27772 {
27773 len = MODE_LINE_NOPROP_LEN (string_start);
27774 str = make_string (mode_line_noprop_buf + string_start, len);
27775 }
27776 else
27777 {
27778 mode_line_string_list = Fnreverse (mode_line_string_list);
27779 str = Fmapconcat (Qidentity, mode_line_string_list,
27780 empty_unibyte_string);
27781 }
27782
27783 return unbind_to (count, str);
27784 }
27785
27786
27787
27788
27789 static void
27790 pint2str (register char *buf, register int width, register ptrdiff_t d)
27791 {
27792 register char *p = buf;
27793
27794 if (d <= 0)
27795 *p++ = '0';
27796 else
27797 {
27798 while (d > 0)
27799 {
27800 *p++ = d % 10 + '0';
27801 d /= 10;
27802 }
27803 }
27804
27805 for (width -= (int) (p - buf); width > 0; --width)
27806 *p++ = ' ';
27807 *p-- = '\0';
27808 while (p > buf)
27809 {
27810 d = *buf;
27811 *buf++ = *p;
27812 *p-- = d;
27813 }
27814 }
27815
27816
27817
27818
27819
27820 static const char power_letter[] =
27821 {
27822 0,
27823 'k',
27824 'M',
27825 'G',
27826 'T',
27827 'P',
27828 'E',
27829 'Z',
27830 'Y',
27831 'R',
27832 'Q'
27833 };
27834
27835 static void
27836 pint2hrstr (char *buf, int width, ptrdiff_t d)
27837 {
27838
27839
27840 ptrdiff_t quotient = d;
27841 int remainder = 0;
27842
27843 int tenths = -1;
27844 int exponent = 0;
27845
27846
27847 int length;
27848
27849 char * psuffix;
27850 char * p;
27851
27852 if (quotient >= 1000)
27853 {
27854
27855 do
27856 {
27857 remainder = quotient % 1000;
27858 quotient /= 1000;
27859 exponent++;
27860 }
27861 while (quotient >= 1000);
27862
27863
27864 if (quotient <= 9)
27865 {
27866 tenths = remainder / 100;
27867 if (remainder % 100 >= 50)
27868 {
27869 if (tenths < 9)
27870 tenths++;
27871 else
27872 {
27873 quotient++;
27874 if (quotient == 10)
27875 tenths = -1;
27876 else
27877 tenths = 0;
27878 }
27879 }
27880 }
27881 else
27882 if (remainder >= 500)
27883 {
27884 if (quotient < 999)
27885 quotient++;
27886 else
27887 {
27888 quotient = 1;
27889 exponent++;
27890 tenths = 0;
27891 }
27892 }
27893 }
27894
27895
27896 if (tenths == -1 && quotient <= 99)
27897 if (quotient <= 9)
27898 length = 1;
27899 else
27900 length = 2;
27901 else
27902 length = 3;
27903 p = psuffix = buf + max (width, length);
27904
27905
27906 *psuffix++ = power_letter[exponent];
27907 *psuffix = '\0';
27908
27909
27910 if (tenths >= 0)
27911 {
27912 *--p = '0' + tenths;
27913 *--p = '.';
27914 }
27915
27916
27917 do
27918 {
27919 int digit = quotient % 10;
27920 *--p = '0' + digit;
27921 }
27922 while ((quotient /= 10) != 0);
27923
27924
27925 while (buf < p)
27926 *--p = ' ';
27927 }
27928
27929
27930
27931
27932
27933 static unsigned char invalid_eol_type[] = "(*invalid*)";
27934
27935 static char *
27936 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
27937 {
27938 Lisp_Object val;
27939 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
27940 const unsigned char *eol_str;
27941 int eol_str_len;
27942
27943 Lisp_Object eoltype;
27944
27945 val = CODING_SYSTEM_SPEC (coding_system);
27946 eoltype = Qnil;
27947
27948 if (!VECTORP (val))
27949 {
27950 *buf++ = multibyte ? '-' : ' ';
27951 if (eol_flag)
27952 eoltype = eol_mnemonic_undecided;
27953
27954 }
27955 else
27956 {
27957 Lisp_Object attrs;
27958 Lisp_Object eolvalue;
27959
27960 attrs = AREF (val, 0);
27961 eolvalue = AREF (val, 2);
27962
27963 if (multibyte)
27964 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
27965 (unsigned char *) buf);
27966 else
27967 *buf++ = ' ';
27968
27969 if (eol_flag)
27970 {
27971
27972
27973 if (NILP (eolvalue))
27974 eoltype = eol_mnemonic_undecided;
27975 else if (VECTORP (eolvalue))
27976 eoltype = eol_mnemonic_undecided;
27977 else
27978 eoltype = (EQ (eolvalue, Qunix)
27979 ? eol_mnemonic_unix
27980 : EQ (eolvalue, Qdos)
27981 ? eol_mnemonic_dos : eol_mnemonic_mac);
27982 }
27983 }
27984
27985 if (eol_flag)
27986 {
27987
27988 if (STRINGP (eoltype))
27989 {
27990 eol_str = SDATA (eoltype);
27991 eol_str_len = SBYTES (eoltype);
27992 }
27993 else if (CHARACTERP (eoltype))
27994 {
27995 int c = XFIXNAT (eoltype);
27996 return buf + CHAR_STRING (c, (unsigned char *) buf);
27997 }
27998 else
27999 {
28000 eol_str = invalid_eol_type;
28001 eol_str_len = sizeof (invalid_eol_type) - 1;
28002 }
28003 memcpy (buf, eol_str, eol_str_len);
28004 buf += eol_str_len;
28005 }
28006
28007 return buf;
28008 }
28009
28010
28011
28012
28013 static int
28014 percent99 (ptrdiff_t n, ptrdiff_t d)
28015 {
28016 int percent = (d - 1 + 100.0 * n) / d;
28017 return min (percent, 99);
28018 }
28019
28020
28021
28022
28023
28024
28025
28026
28027
28028 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28029
28030 static const char *
28031 decode_mode_spec (struct window *w, register int c, int field_width,
28032 Lisp_Object *string)
28033 {
28034 Lisp_Object obj;
28035 struct frame *f = XFRAME (WINDOW_FRAME (w));
28036 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28037
28038
28039
28040
28041
28042 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28043 struct buffer *b = current_buffer;
28044
28045 obj = Qnil;
28046 *string = Qnil;
28047
28048 switch (c)
28049 {
28050 case '*':
28051 if (!NILP (BVAR (b, read_only)))
28052 return "%";
28053 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28054 return "*";
28055 return "-";
28056
28057 case '+':
28058
28059 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28060 return "*";
28061 if (!NILP (BVAR (b, read_only)))
28062 return "%";
28063 return "-";
28064
28065 case '&':
28066
28067 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28068 return "*";
28069 return "-";
28070
28071 case '%':
28072 return "%";
28073
28074 case '[':
28075 {
28076 int i;
28077 char *p;
28078
28079 if (command_loop_level > 5)
28080 return "[[[... ";
28081 p = decode_mode_spec_buf;
28082 for (i = 0; i < command_loop_level; i++)
28083 *p++ = '[';
28084 *p = 0;
28085 return decode_mode_spec_buf;
28086 }
28087
28088 case ']':
28089 {
28090 int i;
28091 char *p;
28092
28093 if (command_loop_level > 5)
28094 return " ...]]]";
28095 p = decode_mode_spec_buf;
28096 for (i = 0; i < command_loop_level; i++)
28097 *p++ = ']';
28098 *p = 0;
28099 return decode_mode_spec_buf;
28100 }
28101
28102 case '-':
28103 {
28104 register int i;
28105
28106
28107 if (mode_line_target == MODE_LINE_NOPROP
28108 || mode_line_target == MODE_LINE_STRING)
28109 return "--";
28110 if (field_width <= 0
28111 || field_width > sizeof (lots_of_dashes))
28112 {
28113 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28114 decode_mode_spec_buf[i] = '-';
28115 decode_mode_spec_buf[i] = '\0';
28116 return decode_mode_spec_buf;
28117 }
28118 else
28119 return lots_of_dashes;
28120 }
28121
28122 case 'b':
28123 obj = BVAR (b, name);
28124 break;
28125
28126 case 'c':
28127 case 'C':
28128
28129
28130
28131
28132
28133 if (mode_line_target == MODE_LINE_TITLE)
28134 return "";
28135 else
28136 {
28137 ptrdiff_t col = current_column ();
28138 int disp_col = (c == 'C') ? col + 1 : col;
28139 w->column_number_displayed = col;
28140 pint2str (decode_mode_spec_buf, width, disp_col);
28141 return decode_mode_spec_buf;
28142 }
28143
28144 case 'e':
28145 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28146 {
28147 if (NILP (Vmemory_full))
28148 return "";
28149 else
28150 return "!MEM FULL! ";
28151 }
28152 #else
28153 return "";
28154 #endif
28155
28156 case 'F':
28157
28158 if (!NILP (f->title))
28159 return SSDATA (f->title);
28160 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28161 return SSDATA (f->name);
28162 return "Emacs";
28163
28164 case 'f':
28165 obj = BVAR (b, filename);
28166 break;
28167
28168 case 'i':
28169 {
28170 ptrdiff_t size = ZV - BEGV;
28171 pint2str (decode_mode_spec_buf, width, size);
28172 return decode_mode_spec_buf;
28173 }
28174
28175 case 'I':
28176 {
28177 ptrdiff_t size = ZV - BEGV;
28178 pint2hrstr (decode_mode_spec_buf, width, size);
28179 return decode_mode_spec_buf;
28180 }
28181
28182 case 'l':
28183 {
28184 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28185 ptrdiff_t topline, nlines, height;
28186 ptrdiff_t junk;
28187
28188
28189 if (mode_line_target == MODE_LINE_TITLE)
28190 return "";
28191
28192 startpos = marker_position (w->start);
28193 startpos_byte = marker_byte_position (w->start);
28194 height = WINDOW_TOTAL_LINES (w);
28195
28196
28197
28198
28199
28200
28201
28202
28203 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28204 && startpos_byte <= BUF_ZV_BYTE (b)))
28205 {
28206 startpos = BUF_BEGV (b);
28207 startpos_byte = BUF_BEGV_BYTE (b);
28208 w->base_line_pos = 0;
28209 w->base_line_number = 0;
28210 }
28211
28212
28213
28214 if (w->base_line_pos == -1)
28215 goto no_value;
28216
28217
28218 if (FIXNUMP (Vline_number_display_limit)
28219 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28220 {
28221 w->base_line_pos = 0;
28222 w->base_line_number = 0;
28223 goto no_value;
28224 }
28225
28226 if (w->base_line_number > 0
28227 && w->base_line_pos > 0
28228 && w->base_line_pos <= startpos)
28229 {
28230 line = w->base_line_number;
28231 linepos = w->base_line_pos;
28232 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28233 }
28234 else
28235 {
28236 line = 1;
28237 linepos = BUF_BEGV (b);
28238 linepos_byte = BUF_BEGV_BYTE (b);
28239 }
28240
28241
28242 nlines = display_count_lines (linepos_byte,
28243 startpos_byte,
28244 startpos, &junk);
28245
28246 topline = nlines + line;
28247
28248
28249
28250
28251
28252 if (startpos == BUF_BEGV (b))
28253 {
28254 w->base_line_number = topline;
28255 w->base_line_pos = BUF_BEGV (b);
28256 }
28257 else if (nlines < height + 25 || nlines > height * 3 + 50
28258 || linepos == BUF_BEGV (b))
28259 {
28260 ptrdiff_t limit = BUF_BEGV (b);
28261 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28262 ptrdiff_t position;
28263 ptrdiff_t distance
28264 = (line_number_display_limit_width < 0 ? 0
28265 : ckd_mul (&distance, line_number_display_limit_width,
28266 height * 2 + 30)
28267 ? PTRDIFF_MAX : distance);
28268
28269 if (startpos - distance > limit)
28270 {
28271 limit = startpos - distance;
28272 limit_byte = CHAR_TO_BYTE (limit);
28273 }
28274
28275 nlines = display_count_lines (startpos_byte,
28276 limit_byte,
28277 - (height * 2 + 30),
28278 &position);
28279
28280
28281
28282 if (position == limit_byte && limit == startpos - distance)
28283 {
28284 w->base_line_pos = -1;
28285 w->base_line_number = 0;
28286 goto no_value;
28287 }
28288
28289 w->base_line_number = topline - nlines;
28290 w->base_line_pos = BYTE_TO_CHAR (position);
28291 }
28292
28293
28294 nlines = display_count_lines (startpos_byte,
28295 PT_BYTE, PT, &junk);
28296
28297
28298 line_number_displayed = true;
28299
28300
28301 pint2str (decode_mode_spec_buf, width, topline + nlines);
28302 return decode_mode_spec_buf;
28303 no_value:
28304 {
28305 char *p = decode_mode_spec_buf;
28306 int pad = width - 2;
28307 while (pad-- > 0)
28308 *p++ = ' ';
28309 *p++ = '?';
28310 *p++ = '?';
28311 *p = '\0';
28312 return decode_mode_spec_buf;
28313 }
28314 }
28315 break;
28316
28317 case 'm':
28318 obj = BVAR (b, mode_name);
28319 break;
28320
28321 case 'n':
28322 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28323 return " Narrow";
28324 break;
28325
28326
28327 case 'o':
28328 {
28329 ptrdiff_t toppos = marker_position (w->start);
28330 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28331 ptrdiff_t begv = BUF_BEGV (b);
28332 ptrdiff_t zv = BUF_ZV (b);
28333
28334 if (zv <= botpos)
28335 return toppos <= begv ? "All" : "Bottom";
28336 else if (toppos <= begv)
28337 return "Top";
28338 else
28339 {
28340 sprintf (decode_mode_spec_buf, "%2d%%",
28341 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28342 return decode_mode_spec_buf;
28343 }
28344 }
28345
28346
28347 case 'p':
28348 {
28349 ptrdiff_t pos = marker_position (w->start);
28350 ptrdiff_t begv = BUF_BEGV (b);
28351 ptrdiff_t zv = BUF_ZV (b);
28352
28353 if (w->window_end_pos <= BUF_Z (b) - zv)
28354 return pos <= begv ? "All" : "Bottom";
28355 else if (pos <= begv)
28356 return "Top";
28357 else
28358 {
28359 sprintf (decode_mode_spec_buf, "%2d%%",
28360 percent99 (pos - begv, zv - begv));
28361 return decode_mode_spec_buf;
28362 }
28363 }
28364
28365
28366 case 'P':
28367 {
28368 ptrdiff_t toppos = marker_position (w->start);
28369 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28370 ptrdiff_t begv = BUF_BEGV (b);
28371 ptrdiff_t zv = BUF_ZV (b);
28372
28373 if (zv <= botpos)
28374 return toppos <= begv ? "All" : "Bottom";
28375 else
28376 {
28377 sprintf (decode_mode_spec_buf,
28378 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28379 percent99 (botpos - begv, zv - begv));
28380 return decode_mode_spec_buf;
28381 }
28382 }
28383
28384
28385
28386 case 'q':
28387 {
28388 ptrdiff_t toppos = marker_position (w->start);
28389 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28390 ptrdiff_t begv = BUF_BEGV (b);
28391 ptrdiff_t zv = BUF_ZV (b);
28392 int top_perc, bot_perc;
28393
28394 if ((toppos <= begv) && (zv <= botpos))
28395 return "All ";
28396
28397 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28398 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28399
28400 if (top_perc == bot_perc)
28401 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28402 else
28403 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28404
28405 return decode_mode_spec_buf;
28406 }
28407
28408 case 's':
28409
28410 obj = Fget_buffer_process (Fcurrent_buffer ());
28411 if (NILP (obj))
28412 return "no process";
28413 #ifndef MSDOS
28414 obj = Fsymbol_name (Fprocess_status (obj));
28415 #endif
28416 break;
28417
28418 case '@':
28419 {
28420 specpdl_ref count = inhibit_garbage_collection ();
28421 Lisp_Object curdir = BVAR (current_buffer, directory);
28422 Lisp_Object val = Qnil;
28423
28424 if (STRINGP (curdir))
28425 val = safe_call1 (intern ("file-remote-p"), curdir);
28426
28427 val = unbind_to (count, val);
28428
28429 if (NILP (val))
28430 return "-";
28431 else
28432 return "@";
28433 }
28434
28435 case 'z':
28436
28437 case 'Z':
28438
28439 {
28440 bool eol_flag = (c == 'Z');
28441 char *p = decode_mode_spec_buf;
28442
28443 if (! FRAME_WINDOW_P (f))
28444 {
28445
28446
28447 p = decode_mode_spec_coding (CODING_ID_NAME
28448 (FRAME_KEYBOARD_CODING (f)->id),
28449 p, false);
28450 p = decode_mode_spec_coding (CODING_ID_NAME
28451 (FRAME_TERMINAL_CODING (f)->id),
28452 p, false);
28453 }
28454 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28455 p, eol_flag);
28456
28457 #if false
28458 #ifdef subprocesses
28459 obj = Fget_buffer_process (Fcurrent_buffer ());
28460 if (PROCESSP (obj))
28461 {
28462 p = decode_mode_spec_coding
28463 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28464 p = decode_mode_spec_coding
28465 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28466 }
28467 #endif
28468 #endif
28469 *p = 0;
28470 return decode_mode_spec_buf;
28471 }
28472 }
28473
28474 if (STRINGP (obj))
28475 {
28476 *string = obj;
28477 return SSDATA (obj);
28478 }
28479 else
28480 return "";
28481 }
28482
28483
28484
28485
28486 ptrdiff_t
28487 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28488 {
28489 ptrdiff_t ignored;
28490 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28491 }
28492
28493
28494
28495
28496
28497
28498
28499
28500
28501
28502
28503 static ptrdiff_t
28504 display_count_lines (ptrdiff_t start_byte,
28505 ptrdiff_t limit_byte, ptrdiff_t count,
28506 ptrdiff_t *byte_pos_ptr)
28507 {
28508 register unsigned char *cursor;
28509 unsigned char *base;
28510
28511 register ptrdiff_t ceiling;
28512 register unsigned char *ceiling_addr;
28513 ptrdiff_t orig_count = count;
28514
28515
28516
28517 bool selective_display
28518 = (!NILP (BVAR (current_buffer, selective_display))
28519 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28520
28521 if (count > 0)
28522 {
28523 while (start_byte < limit_byte)
28524 {
28525 ceiling = BUFFER_CEILING_OF (start_byte);
28526 ceiling = min (limit_byte - 1, ceiling);
28527 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28528 base = (cursor = BYTE_POS_ADDR (start_byte));
28529
28530 do
28531 {
28532 if (selective_display)
28533 {
28534 while (*cursor != '\n' && *cursor != 015
28535 && ++cursor != ceiling_addr)
28536 continue;
28537 if (cursor == ceiling_addr)
28538 break;
28539 }
28540 else
28541 {
28542 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28543 if (! cursor)
28544 break;
28545 }
28546
28547 cursor++;
28548
28549 if (--count == 0)
28550 {
28551 start_byte += cursor - base;
28552 *byte_pos_ptr = start_byte;
28553 return orig_count;
28554 }
28555 }
28556 while (cursor < ceiling_addr);
28557
28558 start_byte += ceiling_addr - base;
28559 }
28560 }
28561 else
28562 {
28563 while (start_byte > limit_byte)
28564 {
28565 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28566 ceiling = max (limit_byte, ceiling);
28567 ceiling_addr = BYTE_POS_ADDR (ceiling);
28568 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28569 while (true)
28570 {
28571 if (selective_display)
28572 {
28573 while (--cursor >= ceiling_addr
28574 && *cursor != '\n' && *cursor != 015)
28575 continue;
28576 if (cursor < ceiling_addr)
28577 break;
28578 }
28579 else
28580 {
28581 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28582 if (! cursor)
28583 break;
28584 }
28585
28586 if (++count == 0)
28587 {
28588 start_byte += cursor - base + 1;
28589 *byte_pos_ptr = start_byte;
28590
28591
28592 return - orig_count - 1;
28593 }
28594 }
28595 start_byte += ceiling_addr - base;
28596 }
28597 }
28598
28599 *byte_pos_ptr = limit_byte;
28600
28601 if (count < 0)
28602 return - orig_count + count;
28603 return orig_count - count;
28604
28605 }
28606
28607
28608
28609
28610
28611
28612
28613
28614
28615
28616
28617
28618
28619
28620
28621
28622
28623
28624
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
28648
28649
28650
28651 static int
28652 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28653 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28654 int field_width, int precision, int max_x, int multibyte)
28655 {
28656 int hpos_at_start = it->hpos;
28657 int saved_face_id = it->face_id;
28658 struct glyph_row *row = it->glyph_row;
28659 ptrdiff_t it_charpos;
28660
28661
28662
28663 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28664 start, precision, field_width, multibyte);
28665
28666 if (string && STRINGP (lisp_string))
28667
28668
28669 it->stop_charpos = it->end_charpos;
28670
28671
28672
28673 if (STRINGP (face_string))
28674 {
28675 ptrdiff_t endptr;
28676 struct face *face;
28677
28678 it->face_id
28679 = face_at_string_position (it->w, face_string, face_string_pos,
28680 0, &endptr, it->base_face_id, false, 0);
28681 face = FACE_FROM_ID (it->f, it->face_id);
28682 it->face_box_p = face->box != FACE_NO_BOX;
28683
28684
28685
28686
28687 if (NILP (lisp_string))
28688 {
28689 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28690 face_string);
28691 if (!NILP (display))
28692 {
28693 Lisp_Object min_width = plist_get (display, Qmin_width);
28694 if (!NILP (min_width))
28695 display_min_width (it, 0, face_string, min_width);
28696 }
28697 }
28698 }
28699
28700
28701
28702 if (max_x <= 0)
28703 max_x = it->last_visible_x;
28704 else
28705 max_x = min (max_x, it->last_visible_x);
28706
28707
28708
28709 if (it->current_x < it->first_visible_x)
28710 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28711 MOVE_TO_POS | MOVE_TO_X);
28712
28713 row->ascent = it->max_ascent;
28714 row->height = it->max_ascent + it->max_descent;
28715 row->phys_ascent = it->max_phys_ascent;
28716 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28717 row->extra_line_spacing = it->max_extra_line_spacing;
28718
28719 if (STRINGP (it->string))
28720 it_charpos = IT_STRING_CHARPOS (*it);
28721 else
28722 it_charpos = IT_CHARPOS (*it);
28723
28724
28725
28726 while (it->current_x < max_x)
28727 {
28728 int x_before, x, n_glyphs_before, i, nglyphs;
28729
28730
28731 if (!get_next_display_element (it))
28732 break;
28733
28734
28735 x_before = it->current_x;
28736 n_glyphs_before = row->used[TEXT_AREA];
28737 PRODUCE_GLYPHS (it);
28738
28739 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28740 i = 0;
28741 x = x_before;
28742 while (i < nglyphs)
28743 {
28744 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28745
28746 if (it->line_wrap != TRUNCATE
28747 && x + glyph->pixel_width > max_x)
28748 {
28749
28750 if (CHAR_GLYPH_PADDING_P (*glyph))
28751 {
28752
28753 if (row->reversed_p)
28754 unproduce_glyphs (it, row->used[TEXT_AREA]
28755 - n_glyphs_before);
28756 row->used[TEXT_AREA] = n_glyphs_before;
28757 it->current_x = x_before;
28758 }
28759 else
28760 {
28761 if (row->reversed_p)
28762 unproduce_glyphs (it, row->used[TEXT_AREA]
28763 - (n_glyphs_before + i));
28764 row->used[TEXT_AREA] = n_glyphs_before + i;
28765 it->current_x = x;
28766 }
28767 break;
28768 }
28769 else if (x + glyph->pixel_width >= it->first_visible_x)
28770 {
28771
28772 ++it->hpos;
28773 if (x < it->first_visible_x)
28774 row->x = x - it->first_visible_x;
28775 }
28776 else
28777 {
28778
28779
28780 emacs_abort ();
28781 }
28782
28783 row->ascent = max (row->ascent, it->max_ascent);
28784 row->height = max (row->height, it->max_ascent + it->max_descent);
28785 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28786 row->phys_height = max (row->phys_height,
28787 it->max_phys_ascent + it->max_phys_descent);
28788 row->extra_line_spacing = max (row->extra_line_spacing,
28789 it->max_extra_line_spacing);
28790 x += glyph->pixel_width;
28791 ++i;
28792 }
28793
28794
28795 if (i < nglyphs)
28796 break;
28797
28798
28799 if (ITERATOR_AT_END_OF_LINE_P (it))
28800 {
28801 it->continuation_lines_width = 0;
28802 break;
28803 }
28804
28805 set_iterator_to_next (it, true);
28806 if (STRINGP (it->string))
28807 it_charpos = IT_STRING_CHARPOS (*it);
28808 else
28809 it_charpos = IT_CHARPOS (*it);
28810
28811
28812 if (it->line_wrap == TRUNCATE
28813 && it->current_x >= it->last_visible_x)
28814 {
28815
28816
28817
28818
28819
28820
28821 if (it_charpos <= it->string_nchars)
28822 {
28823 if (!FRAME_WINDOW_P (it->f))
28824 {
28825 int ii, n;
28826
28827 if (it->current_x > it->last_visible_x)
28828 {
28829
28830
28831 bool mode_line_p = false;
28832
28833
28834
28835 if (row->mode_line_p)
28836 {
28837 struct window *w = it->w;
28838 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
28839 mode_line_p = true;
28840 }
28841 if (!row->reversed_p)
28842 {
28843 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28844 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28845 break;
28846 }
28847 else
28848 {
28849 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28850 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28851 break;
28852 unproduce_glyphs (it, ii + 1);
28853 ii = row->used[TEXT_AREA] - (ii + 1);
28854 }
28855 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28856 {
28857 row->used[TEXT_AREA] = ii;
28858 if (row->mode_line_p)
28859 pad_mode_line (it, mode_line_p);
28860 else
28861 produce_special_glyphs (it, IT_TRUNCATION);
28862 }
28863 }
28864 produce_special_glyphs (it, IT_TRUNCATION);
28865 }
28866 row->truncated_on_right_p = true;
28867 }
28868 break;
28869 }
28870 }
28871
28872
28873 if (it->first_visible_x
28874 && it_charpos > 0)
28875 {
28876 if (!FRAME_WINDOW_P (it->f)
28877 || (row->reversed_p
28878 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
28879 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
28880 insert_left_trunc_glyphs (it);
28881 row->truncated_on_left_p = true;
28882 }
28883
28884 it->face_id = saved_face_id;
28885
28886
28887 return it->hpos - hpos_at_start;
28888 }
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900 int
28901 invisible_prop (Lisp_Object propval, Lisp_Object list)
28902 {
28903 Lisp_Object tail, proptail;
28904
28905 for (tail = list; CONSP (tail); tail = XCDR (tail))
28906 {
28907 register Lisp_Object tem;
28908 tem = XCAR (tail);
28909 if (EQ (propval, tem))
28910 return 1;
28911 if (CONSP (tem) && EQ (propval, XCAR (tem)))
28912 return NILP (XCDR (tem)) ? 1 : 2;
28913 }
28914
28915 if (CONSP (propval))
28916 {
28917 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
28918 {
28919 Lisp_Object propelt;
28920 propelt = XCAR (proptail);
28921 for (tail = list; CONSP (tail); tail = XCDR (tail))
28922 {
28923 register Lisp_Object tem;
28924 tem = XCAR (tail);
28925 if (EQ (propelt, tem))
28926 return 1;
28927 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
28928 return NILP (XCDR (tem)) ? 1 : 2;
28929 }
28930 }
28931 }
28932
28933 return 0;
28934 }
28935
28936 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
28937 doc:
28938
28939
28940
28941
28942
28943
28944
28945
28946
28947
28948
28949 )
28950 (Lisp_Object pos)
28951 {
28952 Lisp_Object prop
28953 = (FIXNATP (pos) || MARKERP (pos)
28954 ? Fget_char_property (pos, Qinvisible, Qnil)
28955 : pos);
28956 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
28957 return (invis == 0 ? Qnil
28958 : invis == 1 ? Qt
28959 : make_fixnum (invis));
28960 }
28961
28962
28963
28964
28965
28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976
28977
28978
28979
28980
28981
28982
28983
28984
28985
28986
28987
28988
28989
28990
28991
28992
28993
28994
28995
28996
28997
28998
28999
29000
29001
29002
29003
29004
29005
29006
29007
29008
29009
29010
29011
29012
29013
29014
29015
29016
29017
29018
29019
29020
29021
29022
29023
29024
29025
29026
29027
29028
29029
29030
29031
29032
29033
29034
29035
29036
29037
29038
29039
29040
29041
29042 static bool
29043 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29044 struct font *font, bool width_p, int *align_to)
29045 {
29046
29047
29048
29049
29050 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29051 double pixels;
29052
29053 # define OK_PIXELS(val) (*res = (val), true)
29054 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29055
29056 if (NILP (prop))
29057 return OK_PIXELS (0);
29058
29059 eassert (FRAME_LIVE_P (it->f));
29060
29061 if (SYMBOLP (prop))
29062 {
29063 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29064 {
29065 char *unit = SSDATA (SYMBOL_NAME (prop));
29066
29067
29068 if (unit[0] == 'i' && unit[1] == 'n')
29069 pixels = 1.0;
29070 else if (unit[0] == 'm' && unit[1] == 'm')
29071 pixels = 25.4;
29072 else if (unit[0] == 'c' && unit[1] == 'm')
29073 pixels = 2.54;
29074 else
29075 pixels = 0;
29076 if (pixels > 0)
29077 {
29078 double ppi = (width_p ? FRAME_RES_X (it->f)
29079 : FRAME_RES_Y (it->f));
29080
29081 if (ppi > 0)
29082 return OK_PIXELS (ppi / pixels);
29083 return false;
29084 }
29085 }
29086
29087 #ifdef HAVE_WINDOW_SYSTEM
29088
29089 if (EQ (prop, Qheight))
29090 return OK_PIXELS (font
29091 ? normal_char_height (font, -1)
29092 : FRAME_LINE_HEIGHT (it->f));
29093
29094 if (EQ (prop, Qwidth))
29095 return OK_PIXELS (font
29096 ? FONT_WIDTH (font)
29097 : FRAME_COLUMN_WIDTH (it->f));
29098 #else
29099 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29100 return OK_PIXELS (1);
29101 #endif
29102
29103
29104 if (EQ (prop, Qtext))
29105 return OK_PIXELS (width_p
29106 ? (window_box_width (it->w, TEXT_AREA)
29107 - lnum_pixel_width)
29108 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29109
29110
29111
29112
29113 if (align_to && *align_to < 0)
29114 {
29115 *res = 0;
29116
29117 if (EQ (prop, Qleft))
29118 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29119 + lnum_pixel_width);
29120
29121 if (EQ (prop, Qright))
29122 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29123
29124 if (EQ (prop, Qcenter))
29125 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29126 + lnum_pixel_width
29127 + window_box_width (it->w, TEXT_AREA) / 2);
29128
29129 if (EQ (prop, Qleft_fringe))
29130 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29131 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29132 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29133
29134 if (EQ (prop, Qright_fringe))
29135 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29136 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29137 : window_box_right_offset (it->w, TEXT_AREA));
29138
29139 if (EQ (prop, Qleft_margin))
29140 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29141
29142 if (EQ (prop, Qright_margin))
29143 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29144
29145 if (EQ (prop, Qscroll_bar))
29146 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29147 ? 0
29148 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29149 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29150 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29151 : 0)));
29152 }
29153 else
29154 {
29155
29156 if (EQ (prop, Qleft_fringe))
29157 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29158 if (EQ (prop, Qright_fringe))
29159 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29160 if (EQ (prop, Qleft_margin))
29161 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29162 if (EQ (prop, Qright_margin))
29163 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29164 if (EQ (prop, Qscroll_bar))
29165 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29166 }
29167
29168 prop = buffer_local_value (prop, it->w->contents);
29169 if (BASE_EQ (prop, Qunbound))
29170 prop = Qnil;
29171 }
29172
29173 if (NUMBERP (prop))
29174 {
29175 int base_unit = (width_p
29176 ? FRAME_COLUMN_WIDTH (it->f)
29177 : FRAME_LINE_HEIGHT (it->f));
29178 if (width_p && align_to && *align_to < 0)
29179 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29180 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29181 }
29182
29183 if (CONSP (prop))
29184 {
29185 Lisp_Object car = XCAR (prop);
29186 Lisp_Object cdr = XCDR (prop);
29187
29188 if (SYMBOLP (car))
29189 {
29190 #ifdef HAVE_WINDOW_SYSTEM
29191
29192 if (FRAME_WINDOW_P (it->f)
29193 && valid_image_p (prop))
29194 {
29195 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29196 struct image *img = IMAGE_FROM_ID (it->f, id);
29197
29198 return OK_PIXELS (width_p ? img->width : img->height);
29199 }
29200
29201 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29202 {
29203
29204 return OK_PIXELS (100);
29205 }
29206 #endif
29207
29208
29209 if (EQ (car, Qplus) || EQ (car, Qminus))
29210 {
29211 bool first = true;
29212 double px;
29213
29214 pixels = 0;
29215 while (CONSP (cdr))
29216 {
29217 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29218 font, width_p, align_to))
29219 return false;
29220 if (first)
29221 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29222 else
29223 pixels += px;
29224 cdr = XCDR (cdr);
29225 }
29226 if (EQ (car, Qminus))
29227 pixels = -pixels;
29228 return OK_PIXELS (pixels);
29229 }
29230
29231 car = buffer_local_value (car, it->w->contents);
29232 if (BASE_EQ (car, Qunbound))
29233 car = Qnil;
29234 }
29235
29236
29237 if (NUMBERP (car))
29238 {
29239 double fact;
29240 int offset =
29241 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29242 pixels = XFLOATINT (car);
29243 if (NILP (cdr))
29244 return OK_PIXELS (pixels + offset);
29245 if (calc_pixel_width_or_height (&fact, it, cdr,
29246 font, width_p, align_to))
29247 return OK_PIXELS (pixels * fact + offset);
29248 return false;
29249 }
29250
29251 return false;
29252 }
29253
29254 return false;
29255 }
29256
29257 void
29258 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29259 {
29260 #ifdef HAVE_WINDOW_SYSTEM
29261 normal_char_ascent_descent (font, -1, ascent, descent);
29262 #else
29263 *ascent = 1;
29264 *descent = 0;
29265 #endif
29266 }
29267
29268
29269
29270
29271
29272
29273 #ifdef HAVE_WINDOW_SYSTEM
29274
29275 #ifdef GLYPH_DEBUG
29276
29277 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29278 void
29279 dump_glyph_string (struct glyph_string *s)
29280 {
29281 fputs ("glyph string\n", stderr);
29282 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29283 s->x, s->y, s->width, s->height);
29284 fprintf (stderr, " ybase = %d\n", s->ybase);
29285 fprintf (stderr, " hl = %u\n", s->hl);
29286 fprintf (stderr, " left overhang = %d, right = %d\n",
29287 s->left_overhang, s->right_overhang);
29288 fprintf (stderr, " nchars = %d\n", s->nchars);
29289 fprintf (stderr, " extends to end of line = %d\n",
29290 s->extends_to_end_of_line_p);
29291 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29292 fprintf (stderr, " bg width = %d\n", s->background_width);
29293 }
29294
29295 #endif
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305 #ifdef HAVE_NTGUI
29306
29307
29308
29309
29310
29311 # define ALLOCATE_HDC(hdc, f) \
29312 Lisp_Object prev_quit = Vinhibit_quit; \
29313 Vinhibit_quit = Qt; \
29314 HDC hdc = get_frame_dc ((f))
29315 # define RELEASE_HDC(hdc, f) \
29316 release_frame_dc ((f), (hdc)); \
29317 Vinhibit_quit = prev_quit
29318 #else
29319 # define ALLOCATE_HDC(hdc, f)
29320 # define RELEASE_HDC(hdc, f)
29321 #endif
29322
29323 static void
29324 init_glyph_string (struct glyph_string *s,
29325 #ifdef HAVE_NTGUI
29326 HDC hdc,
29327 #endif
29328 unsigned *char2b, struct window *w, struct glyph_row *row,
29329 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29330 {
29331 memset (s, 0, sizeof *s);
29332 s->w = w;
29333 s->f = XFRAME (w->frame);
29334 #ifdef HAVE_NTGUI
29335 s->hdc = hdc;
29336 #endif
29337 s->char2b = char2b;
29338 s->hl = hl;
29339 s->row = row;
29340 s->area = area;
29341 s->first_glyph = row->glyphs[area] + start;
29342 s->height = row->height;
29343 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29344 s->ybase = s->y + row->ascent;
29345 }
29346
29347
29348
29349
29350
29351 static void
29352 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29353 struct glyph_string *h, struct glyph_string *t)
29354 {
29355 if (h)
29356 {
29357 if (*head)
29358 (*tail)->next = h;
29359 else
29360 *head = h;
29361 h->prev = *tail;
29362 *tail = t;
29363 }
29364 }
29365
29366
29367
29368
29369
29370
29371 static void
29372 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29373 struct glyph_string *h, struct glyph_string *t)
29374 {
29375 if (h)
29376 {
29377 if (*head)
29378 (*head)->prev = t;
29379 else
29380 *tail = t;
29381 t->next = *head;
29382 *head = h;
29383 }
29384 }
29385
29386
29387
29388
29389
29390 static void
29391 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29392 struct glyph_string *s)
29393 {
29394 s->next = s->prev = NULL;
29395 append_glyph_string_lists (head, tail, s, s);
29396 }
29397
29398
29399
29400
29401
29402
29403
29404
29405 static struct face *
29406 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29407 unsigned *char2b, bool display_p)
29408 {
29409 struct face *face = FACE_FROM_ID (f, face_id);
29410 unsigned code = 0;
29411
29412 if (face->font)
29413 {
29414 code = face->font->driver->encode_char (face->font, c);
29415
29416 if (code == FONT_INVALID_CODE)
29417 code = 0;
29418 }
29419
29420 *char2b = code & 0xFFFF;
29421
29422
29423 #ifdef HAVE_X_WINDOWS
29424 if (display_p)
29425 #endif
29426 {
29427 eassert (face != NULL);
29428 prepare_face_for_display (f, face);
29429 }
29430
29431 return face;
29432 }
29433
29434
29435
29436
29437
29438
29439 static struct face *
29440 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29441 unsigned *char2b)
29442 {
29443 struct face *face;
29444 unsigned code = 0;
29445
29446 eassert (glyph->type == CHAR_GLYPH);
29447 face = FACE_FROM_ID (f, glyph->face_id);
29448
29449
29450 prepare_face_for_display (f, face);
29451
29452 if (face->font)
29453 {
29454 if (CHAR_BYTE8_P (glyph->u.ch))
29455 code = CHAR_TO_BYTE8 (glyph->u.ch);
29456 else
29457 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29458
29459 if (code == FONT_INVALID_CODE)
29460 code = 0;
29461 }
29462
29463
29464 *char2b = code & 0xFFFF;
29465 return face;
29466 }
29467
29468
29469
29470
29471
29472 static bool
29473 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29474 {
29475 unsigned code;
29476
29477 if (CHAR_BYTE8_P (c))
29478 code = CHAR_TO_BYTE8 (c);
29479 else
29480 code = font->driver->encode_char (font, c);
29481
29482 if (code == FONT_INVALID_CODE)
29483 return false;
29484
29485
29486 *char2b = code & 0xFFFF;
29487 return true;
29488 }
29489
29490
29491
29492
29493
29494
29495
29496
29497
29498
29499
29500
29501 static int
29502 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29503 int overlaps)
29504 {
29505 int i;
29506
29507
29508
29509 struct face *face;
29510
29511 eassert (s);
29512
29513 s->for_overlaps = overlaps;
29514 s->face = NULL;
29515 s->font = NULL;
29516 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29517 {
29518 int c = COMPOSITION_GLYPH (s->cmp, i);
29519
29520
29521
29522 if (c != '\t')
29523 {
29524 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29525 -1, Qnil);
29526
29527 face = get_char_face_and_encoding (s->f, c, face_id,
29528 s->char2b + i, true);
29529 if (face)
29530 {
29531 if (! s->face)
29532 {
29533 s->face = face;
29534 s->font = s->face->font;
29535 }
29536 else if (s->face != face)
29537 break;
29538 }
29539 }
29540 ++s->nchars;
29541 }
29542 s->cmp_to = i;
29543
29544 if (s->face == NULL)
29545 {
29546 s->face = base_face->ascii_face;
29547 s->font = s->face->font;
29548 }
29549
29550 if (s->hl == DRAW_MOUSE_FACE
29551 || (s->hl == DRAW_CURSOR
29552 && MATRIX_ROW (s->w->current_matrix,
29553 s->w->phys_cursor.vpos)->mouse_face_p
29554 && cursor_in_mouse_face_p (s->w)))
29555 {
29556 int c = COMPOSITION_GLYPH (s->cmp, 0);
29557 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29558 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29559 if (!s->face)
29560 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29561
29562 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29563 prepare_face_for_display (s->f, s->face);
29564 }
29565
29566
29567
29568 s->width = s->first_glyph->pixel_width;
29569
29570
29571
29572
29573
29574 if (s->font == NULL)
29575 {
29576 s->font_not_found_p = true;
29577 s->font = FRAME_FONT (s->f);
29578 }
29579
29580
29581 s->ybase += s->first_glyph->voffset;
29582
29583 return s->cmp_to;
29584 }
29585
29586 static int
29587 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29588 int start, int end, int overlaps)
29589 {
29590 struct glyph *glyph, *last;
29591 int voffset;
29592 Lisp_Object lgstring;
29593 int i;
29594 bool glyph_not_available_p;
29595
29596 s->for_overlaps = overlaps;
29597 glyph = s->row->glyphs[s->area] + start;
29598 last = s->row->glyphs[s->area] + end;
29599 voffset = glyph->voffset;
29600 glyph_not_available_p = glyph->glyph_not_available_p;
29601 s->cmp_id = glyph->u.cmp.id;
29602 s->cmp_from = glyph->slice.cmp.from;
29603 s->cmp_to = glyph->slice.cmp.to + 1;
29604 if (s->hl == DRAW_MOUSE_FACE
29605 || (s->hl == DRAW_CURSOR
29606 && MATRIX_ROW (s->w->current_matrix,
29607 s->w->phys_cursor.vpos)->mouse_face_p
29608 && cursor_in_mouse_face_p (s->w)))
29609 {
29610 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29611 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29612 if (!s->face)
29613 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29614 prepare_face_for_display (s->f, s->face);
29615 }
29616 else
29617 s->face = FACE_FROM_ID (s->f, face_id);
29618 lgstring = composition_gstring_from_id (s->cmp_id);
29619 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29620
29621
29622 s->width = s->first_glyph->pixel_width;
29623 glyph++;
29624 while (glyph < last
29625 && glyph->u.cmp.automatic
29626 && glyph->u.cmp.id == s->cmp_id
29627 && glyph->face_id == face_id
29628 && s->cmp_to == glyph->slice.cmp.from
29629 && glyph->glyph_not_available_p == glyph_not_available_p)
29630 {
29631 s->width += glyph->pixel_width;
29632 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29633 }
29634
29635 for (i = s->cmp_from; i < s->cmp_to; i++)
29636 {
29637 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29638 unsigned code = LGLYPH_CODE (lglyph);
29639
29640
29641 s->char2b[i] = code & 0xFFFF;
29642 }
29643
29644
29645
29646
29647 if (glyph_not_available_p)
29648 s->font_not_found_p = true;
29649
29650
29651 s->ybase += voffset;
29652
29653 return glyph - s->row->glyphs[s->area];
29654 }
29655
29656
29657
29658
29659
29660
29661
29662 static int
29663 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29664 int start, int end, int overlaps)
29665 {
29666 struct glyph *glyph, *last;
29667 int voffset;
29668
29669 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29670 s->for_overlaps = overlaps;
29671 glyph = s->row->glyphs[s->area] + start;
29672 last = s->row->glyphs[s->area] + end;
29673 voffset = glyph->voffset;
29674 s->face = FACE_FROM_ID (s->f, face_id);
29675 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29676 if (s->hl == DRAW_MOUSE_FACE
29677 || (s->hl == DRAW_CURSOR
29678 && MATRIX_ROW (s->w->current_matrix,
29679 s->w->phys_cursor.vpos)->mouse_face_p
29680 && cursor_in_mouse_face_p (s->w)))
29681 {
29682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29683 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29684 if (!s->face)
29685 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29686 prepare_face_for_display (s->f, s->face);
29687 }
29688 s->nchars = 1;
29689 s->width = glyph->pixel_width;
29690 glyph++;
29691 while (glyph < last
29692 && glyph->type == GLYPHLESS_GLYPH
29693 && glyph->voffset == voffset
29694 && glyph->face_id == face_id)
29695 {
29696 s->nchars++;
29697 s->width += glyph->pixel_width;
29698 glyph++;
29699 }
29700 s->ybase += voffset;
29701 return glyph - s->row->glyphs[s->area];
29702 }
29703
29704
29705
29706
29707
29708
29709
29710
29711
29712
29713
29714 static int
29715 fill_glyph_string (struct glyph_string *s, int face_id,
29716 int start, int end, int overlaps)
29717 {
29718 struct glyph *glyph, *last;
29719 int voffset;
29720 bool glyph_not_available_p;
29721
29722 eassert (s->f == XFRAME (s->w->frame));
29723 eassert (s->nchars == 0);
29724 eassert (start >= 0 && end > start);
29725
29726 s->for_overlaps = overlaps;
29727 glyph = s->row->glyphs[s->area] + start;
29728 last = s->row->glyphs[s->area] + end;
29729 voffset = glyph->voffset;
29730 s->padding_p = glyph->padding_p;
29731 glyph_not_available_p = glyph->glyph_not_available_p;
29732
29733 while (glyph < last
29734 && glyph->type == CHAR_GLYPH
29735 && glyph->voffset == voffset
29736
29737 && glyph->face_id == face_id
29738 && glyph->glyph_not_available_p == glyph_not_available_p)
29739 {
29740 s->face = get_glyph_face_and_encoding (s->f, glyph,
29741 s->char2b + s->nchars);
29742 ++s->nchars;
29743 eassert (s->nchars <= end - start);
29744 s->width += glyph->pixel_width;
29745 if (glyph++->padding_p != s->padding_p)
29746 break;
29747 }
29748
29749 s->font = s->face->font;
29750
29751 if (s->hl == DRAW_MOUSE_FACE
29752 || (s->hl == DRAW_CURSOR
29753 && MATRIX_ROW (s->w->current_matrix,
29754 s->w->phys_cursor.vpos)->mouse_face_p
29755 && cursor_in_mouse_face_p (s->w)))
29756 {
29757 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29758 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29759 if (!s->face)
29760 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29761 s->face
29762 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29763 s->first_glyph->u.ch, -1, Qnil));
29764 prepare_face_for_display (s->f, s->face);
29765 }
29766
29767
29768
29769
29770
29771 if (s->font == NULL || glyph_not_available_p)
29772 {
29773 s->font_not_found_p = true;
29774 s->font = FRAME_FONT (s->f);
29775 }
29776
29777
29778 s->ybase += voffset;
29779
29780 eassert (s->face && s->face->gc);
29781 return glyph - s->row->glyphs[s->area];
29782 }
29783
29784
29785
29786
29787 static void
29788 fill_image_glyph_string (struct glyph_string *s)
29789 {
29790 eassert (s->first_glyph->type == IMAGE_GLYPH);
29791 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29792 eassert (s->img);
29793 s->slice = s->first_glyph->slice.img;
29794 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29795 s->font = s->face->font;
29796 if (s->hl == DRAW_MOUSE_FACE
29797 || (s->hl == DRAW_CURSOR
29798 && MATRIX_ROW (s->w->current_matrix,
29799 s->w->phys_cursor.vpos)->mouse_face_p
29800 && cursor_in_mouse_face_p (s->w)))
29801 {
29802 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29803 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29804 if (!s->face)
29805 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29806 prepare_face_for_display (s->f, s->face);
29807 }
29808 s->width = s->first_glyph->pixel_width;
29809
29810
29811 s->ybase += s->first_glyph->voffset;
29812 }
29813
29814
29815 #ifdef HAVE_XWIDGETS
29816 static void
29817 fill_xwidget_glyph_string (struct glyph_string *s)
29818 {
29819 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29820 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29821 s->font = s->face->font;
29822 if (s->hl == DRAW_MOUSE_FACE
29823 || (s->hl == DRAW_CURSOR
29824 && MATRIX_ROW (s->w->current_matrix,
29825 s->w->phys_cursor.vpos)->mouse_face_p
29826 && cursor_in_mouse_face_p (s->w)))
29827 {
29828 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29829 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29830 if (!s->face)
29831 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29832 prepare_face_for_display (s->f, s->face);
29833 }
29834 s->width = s->first_glyph->pixel_width;
29835 s->ybase += s->first_glyph->voffset;
29836 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29837 }
29838 #endif
29839
29840
29841
29842
29843
29844
29845
29846 static int
29847 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29848 {
29849 struct glyph *glyph, *last;
29850 int voffset, face_id;
29851
29852 eassert (s->first_glyph->type == STRETCH_GLYPH);
29853
29854 glyph = s->row->glyphs[s->area] + start;
29855 last = s->row->glyphs[s->area] + end;
29856 face_id = glyph->face_id;
29857 s->face = FACE_FROM_ID (s->f, face_id);
29858 s->font = s->face->font;
29859 if (s->hl == DRAW_MOUSE_FACE
29860 || (s->hl == DRAW_CURSOR
29861 && MATRIX_ROW (s->w->current_matrix,
29862 s->w->phys_cursor.vpos)->mouse_face_p
29863 && cursor_in_mouse_face_p (s->w)))
29864 {
29865 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29866 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29867 if (!s->face)
29868 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29869 prepare_face_for_display (s->f, s->face);
29870 }
29871 s->width = glyph->pixel_width;
29872 s->nchars = 1;
29873 voffset = glyph->voffset;
29874
29875 for (++glyph;
29876 (glyph < last
29877 && glyph->type == STRETCH_GLYPH
29878 && glyph->voffset == voffset
29879 && glyph->face_id == face_id);
29880 ++glyph)
29881 s->width += glyph->pixel_width;
29882
29883
29884 s->ybase += voffset;
29885
29886
29887
29888 eassert (s->face);
29889 return glyph - s->row->glyphs[s->area];
29890 }
29891
29892 static struct font_metrics *
29893 get_per_char_metric (struct font *font, const unsigned *char2b)
29894 {
29895 static struct font_metrics metrics;
29896
29897 if (! font)
29898 return NULL;
29899 if (*char2b == FONT_INVALID_CODE)
29900 return NULL;
29901
29902 font->driver->text_extents (font, char2b, 1, &metrics);
29903 return &metrics;
29904 }
29905
29906
29907
29908
29909
29910
29911
29912 static void
29913 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
29914 {
29915 *ascent = FONT_BASE (font);
29916 *descent = FONT_DESCENT (font);
29917
29918 if (FONT_TOO_HIGH (font))
29919 {
29920 unsigned char2b;
29921
29922
29923
29924 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
29925 {
29926 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
29927 eassume (pcm);
29928
29929 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
29930 {
29931
29932
29933
29934 *ascent = pcm->ascent + 1;
29935 *descent = pcm->descent + 1;
29936 }
29937 }
29938 }
29939 }
29940
29941
29942
29943
29944
29945
29946 static int
29947 normal_char_height (struct font *font, int c)
29948 {
29949 int ascent, descent;
29950
29951 normal_char_ascent_descent (font, c, &ascent, &descent);
29952
29953 return ascent + descent;
29954 }
29955
29956
29957
29958
29959
29960
29961 void
29962 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
29963 {
29964 *left = *right = 0;
29965
29966 if (glyph->type == CHAR_GLYPH)
29967 {
29968 unsigned char2b;
29969 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
29970 if (face->font)
29971 {
29972 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
29973 if (pcm)
29974 {
29975 if (pcm->rbearing > pcm->width)
29976 *right = pcm->rbearing - pcm->width;
29977 if (pcm->lbearing < 0)
29978 *left = -pcm->lbearing;
29979 }
29980 }
29981 }
29982 else if (glyph->type == COMPOSITE_GLYPH)
29983 {
29984 if (! glyph->u.cmp.automatic)
29985 {
29986 struct composition *cmp = composition_table[glyph->u.cmp.id];
29987
29988 if (cmp->rbearing > cmp->pixel_width)
29989 *right = cmp->rbearing - cmp->pixel_width;
29990 if (cmp->lbearing < 0)
29991 *left = - cmp->lbearing;
29992 }
29993 else
29994 {
29995 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
29996 struct font_metrics metrics;
29997
29998 composition_gstring_width (gstring, glyph->slice.cmp.from,
29999 glyph->slice.cmp.to + 1, &metrics);
30000 if (metrics.rbearing > metrics.width)
30001 *right = metrics.rbearing - metrics.width;
30002 if (metrics.lbearing < 0)
30003 *left = - metrics.lbearing;
30004 }
30005 }
30006 }
30007
30008
30009
30010
30011
30012
30013 static int
30014 left_overwritten (struct glyph_string *s)
30015 {
30016 int k;
30017
30018 if (s->left_overhang)
30019 {
30020 int x = 0, i;
30021 struct glyph *glyphs = s->row->glyphs[s->area];
30022 int first = s->first_glyph - glyphs;
30023
30024 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30025 x -= glyphs[i].pixel_width;
30026
30027 k = i + 1;
30028 }
30029 else
30030 k = -1;
30031
30032 return k;
30033 }
30034
30035
30036
30037
30038
30039
30040 static int
30041 left_overwriting (struct glyph_string *s)
30042 {
30043 int i, k, x;
30044 struct glyph *glyphs = s->row->glyphs[s->area];
30045 int first = s->first_glyph - glyphs;
30046
30047 k = -1;
30048 x = 0;
30049 for (i = first - 1; i >= 0; --i)
30050 {
30051 int left, right;
30052 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30053 if (x + right > 0)
30054 k = i;
30055 x -= glyphs[i].pixel_width;
30056 }
30057
30058 return k;
30059 }
30060
30061
30062
30063
30064
30065
30066 static int
30067 right_overwritten (struct glyph_string *s)
30068 {
30069 int k = -1;
30070
30071 if (s->right_overhang)
30072 {
30073 int x = 0, i;
30074 struct glyph *glyphs = s->row->glyphs[s->area];
30075 int first = (s->first_glyph - glyphs
30076 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30077 int end = s->row->used[s->area];
30078
30079 for (i = first; i < end && s->right_overhang > x; ++i)
30080 x += glyphs[i].pixel_width;
30081
30082 k = i;
30083 }
30084
30085 return k;
30086 }
30087
30088
30089
30090
30091
30092
30093 static int
30094 right_overwriting (struct glyph_string *s)
30095 {
30096 int i, k, x;
30097 int end = s->row->used[s->area];
30098 struct glyph *glyphs = s->row->glyphs[s->area];
30099 int first = (s->first_glyph - glyphs
30100 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30101
30102 k = -1;
30103 x = 0;
30104 for (i = first; i < end; ++i)
30105 {
30106 int left, right;
30107 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30108 if (x - left < 0)
30109 k = i;
30110 x += glyphs[i].pixel_width;
30111 }
30112
30113 return k;
30114 }
30115
30116
30117
30118
30119
30120
30121
30122
30123
30124
30125
30126 static void
30127 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30128 {
30129
30130
30131
30132 if (start == s->row->used[s->area]
30133 && ((s->row->fill_line_p
30134 && (s->hl == DRAW_NORMAL_TEXT
30135 || s->hl == DRAW_IMAGE_RAISED
30136 || s->hl == DRAW_IMAGE_SUNKEN))
30137 || s->hl == DRAW_MOUSE_FACE))
30138 s->extends_to_end_of_line_p = true;
30139
30140
30141
30142
30143 if (s->extends_to_end_of_line_p)
30144 s->background_width = last_x - s->x + 1;
30145 else
30146 {
30147 s->background_width = s->width;
30148 #ifdef HAVE_WINDOW_SYSTEM
30149 if (FRAME_WINDOW_P (s->f)
30150 && s->hl == DRAW_CURSOR
30151 && MATRIX_ROW (s->w->current_matrix,
30152 s->w->phys_cursor.vpos)->mouse_face_p
30153 && cursor_in_mouse_face_p (s->w))
30154 {
30155
30156
30157
30158
30159 struct glyph *g = s->first_glyph;
30160 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30161 s->background_width +=
30162 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30163 regular_face, s->face);
30164
30165 s->width = s->background_width;
30166 }
30167 #endif
30168 }
30169 }
30170
30171
30172
30173
30174
30175 static struct glyph_string *
30176 glyph_string_containing_background_width (struct glyph_string *s)
30177 {
30178 if (s->cmp)
30179 while (s->cmp_from)
30180 s = s->prev;
30181
30182 return s;
30183 }
30184
30185
30186
30187
30188
30189
30190 static void
30191 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30192 {
30193 if (backward_p)
30194 {
30195 while (s)
30196 {
30197 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30198 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30199 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30200 x -= s->width;
30201 s->x = x;
30202 s = s->prev;
30203 }
30204 }
30205 else
30206 {
30207 while (s)
30208 {
30209 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30210 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30211 s->x = x;
30212 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30213 x += s->width;
30214 s = s->next;
30215 }
30216 }
30217 }
30218
30219
30220
30221
30222
30223
30224
30225
30226
30227 #ifdef HAVE_NTGUI
30228
30229
30230 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30231 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30232 #else
30233 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30234 init_glyph_string (s, char2b, w, row, area, start, hl)
30235 #endif
30236
30237
30238
30239
30240
30241
30242
30243
30244
30245
30246
30247 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30248 do \
30249 { \
30250 s = alloca (sizeof *s); \
30251 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30252 START = fill_stretch_glyph_string (s, START, END); \
30253 append_glyph_string (&HEAD, &TAIL, s); \
30254 s->x = (X); \
30255 } \
30256 while (false)
30257
30258
30259
30260
30261
30262
30263
30264
30265
30266
30267 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30268 do \
30269 { \
30270 s = alloca (sizeof *s); \
30271 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30272 fill_image_glyph_string (s); \
30273 append_glyph_string (&HEAD, &TAIL, s); \
30274 ++START; \
30275 s->x = (X); \
30276 } \
30277 while (false)
30278
30279 #ifndef HAVE_XWIDGETS
30280 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30281 eassume (false)
30282 #else
30283 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30284 do \
30285 { \
30286 s = alloca (sizeof *s); \
30287 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30288 fill_xwidget_glyph_string (s); \
30289 append_glyph_string (&(HEAD), &(TAIL), s); \
30290 ++(START); \
30291 s->x = (X); \
30292 } \
30293 while (false)
30294 #endif
30295
30296
30297
30298
30299
30300
30301
30302
30303
30304
30305 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30306 do \
30307 { \
30308 int face_id; \
30309 unsigned *char2b; \
30310 \
30311 face_id = (row)->glyphs[area][START].face_id; \
30312 \
30313 s = alloca (sizeof *s); \
30314 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30315 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30316 append_glyph_string (&HEAD, &TAIL, s); \
30317 s->x = (X); \
30318 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30319 } \
30320 while (false)
30321
30322
30323
30324
30325
30326
30327
30328
30329
30330
30331
30332 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30333 do { \
30334 int face_id = (row)->glyphs[area][START].face_id; \
30335 struct face *base_face = FACE_FROM_ID (f, face_id); \
30336 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30337 struct composition *cmp = composition_table[cmp_id]; \
30338 unsigned *char2b; \
30339 struct glyph_string *first_s = NULL; \
30340 int n; \
30341 \
30342 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30343 \
30344
30345 \
30346 for (n = 0; n < cmp->glyph_len;) \
30347 { \
30348 s = alloca (sizeof *s); \
30349 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30350 append_glyph_string (&(HEAD), &(TAIL), s); \
30351 s->cmp = cmp; \
30352 s->cmp_from = n; \
30353 s->x = (X); \
30354 if (n == 0) \
30355 first_s = s; \
30356 n = fill_composite_glyph_string (s, base_face, overlaps); \
30357 } \
30358 \
30359 ++START; \
30360 s = first_s; \
30361 } while (false)
30362
30363
30364
30365
30366
30367 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30368 do { \
30369 int face_id; \
30370 unsigned *char2b; \
30371 Lisp_Object gstring; \
30372 \
30373 face_id = (row)->glyphs[area][START].face_id; \
30374 gstring = (composition_gstring_from_id \
30375 ((row)->glyphs[area][START].u.cmp.id)); \
30376 s = alloca (sizeof *s); \
30377 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30378 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30379 append_glyph_string (&(HEAD), &(TAIL), s); \
30380 s->x = (X); \
30381 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30382 } while (false)
30383
30384
30385
30386
30387
30388
30389 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30390 do \
30391 { \
30392 int face_id; \
30393 \
30394 face_id = (row)->glyphs[area][START].face_id; \
30395 \
30396 s = alloca (sizeof *s); \
30397 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30398 append_glyph_string (&HEAD, &TAIL, s); \
30399 s->x = (X); \
30400 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30401 overlaps); \
30402 } \
30403 while (false)
30404
30405
30406
30407
30408
30409
30410
30411
30412
30413
30414
30415
30416 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30417 do \
30418 { \
30419 HEAD = TAIL = NULL; \
30420 while (START < END) \
30421 { \
30422 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30423 switch (first_glyph->type) \
30424 { \
30425 case CHAR_GLYPH: \
30426 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30427 HL, X, LAST_X); \
30428 break; \
30429 \
30430 case COMPOSITE_GLYPH: \
30431 if (first_glyph->u.cmp.automatic) \
30432 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30433 HL, X, LAST_X); \
30434 else \
30435 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30436 HL, X, LAST_X); \
30437 break; \
30438 \
30439 case STRETCH_GLYPH: \
30440 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30441 HL, X, LAST_X); \
30442 break; \
30443 \
30444 case IMAGE_GLYPH: \
30445 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30446 HL, X, LAST_X); \
30447 break;
30448
30449 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30450 case XWIDGET_GLYPH: \
30451 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30452 HL, X, LAST_X); \
30453 break;
30454
30455 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30456 case GLYPHLESS_GLYPH: \
30457 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30458 HL, X, LAST_X); \
30459 break; \
30460 \
30461 default: \
30462 emacs_abort (); \
30463 } \
30464 \
30465 if (s) \
30466 { \
30467 set_glyph_string_background_width (s, START, LAST_X); \
30468 (X) += s->width; \
30469 } \
30470 } \
30471 } while (false)
30472
30473
30474 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30475 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30476 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30477 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30478
30479
30480
30481
30482
30483
30484
30485
30486
30487
30488
30489
30490
30491
30492
30493
30494
30495
30496
30497
30498
30499
30500
30501
30502 static int
30503 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30504 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30505 enum draw_glyphs_face hl, int overlaps)
30506 {
30507 struct glyph_string *head, *tail;
30508 struct glyph_string *s;
30509 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30510 int i, j, x_reached, last_x, area_left = 0;
30511 struct frame *f = XFRAME (WINDOW_FRAME (w));
30512
30513 ALLOCATE_HDC (hdc, f);
30514
30515
30516 end = min (end, row->used[area]);
30517 start = clip_to_bounds (0, start, end);
30518
30519
30520
30521 if (row->full_width_p)
30522 {
30523
30524
30525 area_left = WINDOW_LEFT_EDGE_X (w);
30526 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30527 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30528 }
30529 else
30530 {
30531 area_left = window_box_left (w, area);
30532 last_x = area_left + window_box_width (w, area);
30533 }
30534 x += area_left;
30535
30536
30537
30538
30539
30540 i = start;
30541 USE_SAFE_ALLOCA;
30542 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30543 if (tail)
30544 {
30545 s = glyph_string_containing_background_width (tail);
30546 x_reached = s->x + s->background_width;
30547 }
30548 else
30549 x_reached = x;
30550
30551
30552
30553
30554 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30555 {
30556 struct glyph_string *h, *t;
30557 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30558 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30559 bool check_mouse_face = false;
30560 int dummy_x = 0;
30561
30562
30563
30564 if (area == TEXT_AREA && row->mouse_face_p
30565 && hlinfo->mouse_face_beg_row >= 0
30566 && hlinfo->mouse_face_end_row >= 0)
30567 {
30568 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30569
30570 if (row_vpos >= hlinfo->mouse_face_beg_row
30571 && row_vpos <= hlinfo->mouse_face_end_row)
30572 {
30573 check_mouse_face = true;
30574 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30575 ? hlinfo->mouse_face_beg_col : 0;
30576 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30577 ? hlinfo->mouse_face_end_col
30578 : row->used[TEXT_AREA];
30579 }
30580 }
30581
30582
30583 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30584 for (s = head; s; s = s->next)
30585 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30586
30587
30588
30589
30590
30591
30592 i = left_overwritten (head);
30593 if (i >= 0)
30594 {
30595 enum draw_glyphs_face overlap_hl;
30596
30597
30598
30599
30600
30601
30602
30603
30604 if (check_mouse_face
30605 && mouse_beg_col < start && mouse_end_col > i)
30606 overlap_hl = DRAW_MOUSE_FACE;
30607 else
30608 overlap_hl = DRAW_NORMAL_TEXT;
30609
30610 if (hl != overlap_hl)
30611 clip_head = head;
30612 j = i;
30613 BUILD_GLYPH_STRINGS (j, start, h, t,
30614 overlap_hl, dummy_x, last_x);
30615 start = i;
30616 compute_overhangs_and_x (t, head->x, true);
30617 prepend_glyph_string_lists (&head, &tail, h, t);
30618 if (clip_head == NULL)
30619 clip_head = head;
30620 }
30621
30622
30623
30624
30625
30626
30627
30628
30629 i = left_overwriting (head);
30630 if (i >= 0)
30631 {
30632 enum draw_glyphs_face overlap_hl;
30633
30634 if (check_mouse_face
30635 && mouse_beg_col < start && mouse_end_col > i)
30636 overlap_hl = DRAW_MOUSE_FACE;
30637 else
30638 overlap_hl = DRAW_NORMAL_TEXT;
30639
30640 if (hl == overlap_hl || clip_head == NULL)
30641 clip_head = head;
30642 BUILD_GLYPH_STRINGS (i, start, h, t,
30643 overlap_hl, dummy_x, last_x);
30644 for (s = h; s; s = s->next)
30645 s->background_filled_p = true;
30646 compute_overhangs_and_x (t, head->x, true);
30647 prepend_glyph_string_lists (&head, &tail, h, t);
30648 }
30649
30650
30651
30652
30653
30654 i = right_overwritten (tail);
30655 if (i >= 0)
30656 {
30657 enum draw_glyphs_face overlap_hl;
30658
30659 if (check_mouse_face
30660 && mouse_beg_col < i && mouse_end_col > end)
30661 overlap_hl = DRAW_MOUSE_FACE;
30662 else
30663 overlap_hl = DRAW_NORMAL_TEXT;
30664
30665 if (hl != overlap_hl)
30666 clip_tail = tail;
30667 BUILD_GLYPH_STRINGS (end, i, h, t,
30668 overlap_hl, x, last_x);
30669
30670
30671 compute_overhangs_and_x (h, tail->x + tail->width, false);
30672 append_glyph_string_lists (&head, &tail, h, t);
30673 if (clip_tail == NULL)
30674 clip_tail = tail;
30675 }
30676
30677
30678
30679
30680
30681
30682 i = right_overwriting (tail);
30683 if (i >= 0)
30684 {
30685 enum draw_glyphs_face overlap_hl;
30686 if (check_mouse_face
30687 && mouse_beg_col < i && mouse_end_col > end)
30688 overlap_hl = DRAW_MOUSE_FACE;
30689 else
30690 overlap_hl = DRAW_NORMAL_TEXT;
30691
30692 if (hl == overlap_hl || clip_tail == NULL)
30693 clip_tail = tail;
30694 i++;
30695 BUILD_GLYPH_STRINGS (end, i, h, t,
30696 overlap_hl, x, last_x);
30697 for (s = h; s; s = s->next)
30698 s->background_filled_p = true;
30699 compute_overhangs_and_x (h, tail->x + tail->width, false);
30700 append_glyph_string_lists (&head, &tail, h, t);
30701 }
30702 tail = glyph_string_containing_background_width (tail);
30703 if (clip_tail)
30704 clip_tail = glyph_string_containing_background_width (clip_tail);
30705 if (clip_head || clip_tail)
30706 for (s = head; s; s = s->next)
30707 {
30708 s->clip_head = clip_head;
30709 s->clip_tail = clip_tail;
30710 }
30711 }
30712
30713
30714 for (s = head; s; s = s->next)
30715 FRAME_RIF (f)->draw_glyph_string (s);
30716
30717
30718
30719 if (area == TEXT_AREA
30720 && !row->full_width_p
30721
30722
30723
30724 && !overlaps)
30725 {
30726 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30727 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30728 : (tail ? tail->x + tail->background_width : x));
30729 x0 -= area_left;
30730 x1 -= area_left;
30731
30732 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30733 row->y, MATRIX_ROW_BOTTOM_Y (row));
30734 }
30735
30736
30737
30738 if (row->full_width_p)
30739 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30740 else
30741 x_reached -= area_left;
30742
30743 RELEASE_HDC (hdc, f);
30744
30745 SAFE_FREE ();
30746 return x_reached;
30747 }
30748
30749
30750
30751
30752
30753
30754
30755
30756 struct font *
30757 font_for_underline_metrics (struct glyph_string *s)
30758 {
30759 struct glyph *g0 = s->row->glyphs[s->area], *g;
30760
30761 for (g = s->first_glyph - 1; g >= g0; g--)
30762 {
30763 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30764 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30765 break;
30766 }
30767
30768
30769 if (g == s->first_glyph - 1)
30770 return s->font;
30771 else
30772 {
30773
30774
30775 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30776 }
30777 }
30778
30779
30780
30781
30782 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30783 { \
30784 if (!it->f->fonts_changed \
30785 && (it->glyph_row->glyphs[area] \
30786 < it->glyph_row->glyphs[area + 1])) \
30787 { \
30788 it->w->ncols_scale_factor++; \
30789 it->f->fonts_changed = true; \
30790 } \
30791 }
30792
30793
30794
30795
30796 static void
30797 append_glyph (struct it *it)
30798 {
30799 struct glyph *glyph;
30800 enum glyph_row_area area = it->area;
30801
30802 eassert (it->glyph_row);
30803 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30804
30805 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30806 if (glyph < it->glyph_row->glyphs[area + 1])
30807 {
30808
30809
30810 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30811 {
30812 struct glyph *g;
30813
30814
30815 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30816 g[1] = *g;
30817 glyph = it->glyph_row->glyphs[area];
30818 }
30819 glyph->charpos = CHARPOS (it->position);
30820 glyph->object = it->object;
30821 if (it->pixel_width > 0)
30822 {
30823 eassert (it->pixel_width <= SHRT_MAX);
30824 glyph->pixel_width = it->pixel_width;
30825 glyph->padding_p = false;
30826 }
30827 else
30828 {
30829
30830
30831 glyph->pixel_width = 1;
30832 glyph->padding_p = true;
30833 }
30834 glyph->ascent = it->ascent;
30835 glyph->descent = it->descent;
30836 glyph->voffset = it->voffset;
30837 glyph->type = CHAR_GLYPH;
30838 glyph->avoid_cursor_p = it->avoid_cursor_p;
30839 glyph->multibyte_p = it->multibyte_p;
30840 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30841 {
30842
30843
30844 glyph->right_box_line_p = it->start_of_box_run_p;
30845 glyph->left_box_line_p = it->end_of_box_run_p;
30846 }
30847 else
30848 {
30849 glyph->left_box_line_p = it->start_of_box_run_p;
30850 glyph->right_box_line_p = it->end_of_box_run_p;
30851 }
30852 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30853 || it->phys_descent > it->descent);
30854 glyph->glyph_not_available_p = it->glyph_not_available_p;
30855 glyph->face_id = it->face_id;
30856 glyph->u.ch = it->char_to_display;
30857 glyph->slice.img = null_glyph_slice;
30858 glyph->font_type = FONT_TYPE_UNKNOWN;
30859 if (it->bidi_p)
30860 {
30861 glyph->resolved_level = it->bidi_it.resolved_level;
30862 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30863 glyph->bidi_type = it->bidi_it.type;
30864 }
30865 else
30866 {
30867 glyph->resolved_level = 0;
30868 glyph->bidi_type = UNKNOWN_BT;
30869 }
30870 ++it->glyph_row->used[area];
30871 }
30872 else
30873 IT_EXPAND_MATRIX_WIDTH (it, area);
30874 }
30875
30876
30877
30878
30879 static void
30880 append_composite_glyph (struct it *it)
30881 {
30882 struct glyph *glyph;
30883 enum glyph_row_area area = it->area;
30884
30885 eassert (it->glyph_row);
30886
30887 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30888 if (glyph < it->glyph_row->glyphs[area + 1])
30889 {
30890
30891
30892 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
30893 {
30894 struct glyph *g;
30895
30896
30897 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30898 g[1] = *g;
30899 glyph = it->glyph_row->glyphs[it->area];
30900 }
30901 glyph->charpos = it->cmp_it.charpos;
30902 glyph->object = it->object;
30903 eassert (it->pixel_width <= SHRT_MAX);
30904 glyph->pixel_width = it->pixel_width;
30905 glyph->ascent = it->ascent;
30906 glyph->descent = it->descent;
30907 glyph->voffset = it->voffset;
30908 glyph->type = COMPOSITE_GLYPH;
30909 if (it->cmp_it.ch < 0)
30910 {
30911 glyph->u.cmp.automatic = false;
30912 glyph->u.cmp.id = it->cmp_it.id;
30913 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
30914 }
30915 else
30916 {
30917 glyph->u.cmp.automatic = true;
30918 glyph->u.cmp.id = it->cmp_it.id;
30919 glyph->slice.cmp.from = it->cmp_it.from;
30920 glyph->slice.cmp.to = it->cmp_it.to - 1;
30921 }
30922 glyph->avoid_cursor_p = it->avoid_cursor_p;
30923 glyph->multibyte_p = it->multibyte_p;
30924 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30925 {
30926
30927
30928 glyph->right_box_line_p = it->start_of_box_run_p;
30929 glyph->left_box_line_p = it->end_of_box_run_p;
30930 }
30931 else
30932 {
30933 glyph->left_box_line_p = it->start_of_box_run_p;
30934 glyph->right_box_line_p = it->end_of_box_run_p;
30935 }
30936 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30937 || it->phys_descent > it->descent);
30938 glyph->padding_p = false;
30939 glyph->glyph_not_available_p = it->glyph_not_available_p;
30940 glyph->face_id = it->face_id;
30941 glyph->font_type = FONT_TYPE_UNKNOWN;
30942 if (it->bidi_p)
30943 {
30944 glyph->resolved_level = it->bidi_it.resolved_level;
30945 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30946 glyph->bidi_type = it->bidi_it.type;
30947 }
30948 ++it->glyph_row->used[area];
30949 }
30950 else
30951 IT_EXPAND_MATRIX_WIDTH (it, area);
30952 }
30953
30954
30955
30956
30957
30958 static void
30959 take_vertical_position_into_account (struct it *it)
30960 {
30961 if (it->voffset)
30962 {
30963 if (it->voffset < 0)
30964
30965
30966 it->ascent -= it->voffset;
30967 else
30968
30969
30970 it->descent += it->voffset;
30971 }
30972 }
30973
30974
30975
30976
30977
30978
30979 static void
30980 produce_image_glyph (struct it *it)
30981 {
30982 struct image *img;
30983 struct face *face;
30984 int glyph_ascent, crop;
30985 struct glyph_slice slice;
30986
30987 eassert (it->what == IT_IMAGE);
30988
30989 face = FACE_FROM_ID (it->f, it->face_id);
30990
30991 prepare_face_for_display (it->f, face);
30992
30993 if (it->image_id < 0)
30994 {
30995
30996 it->ascent = it->phys_ascent = 0;
30997 it->descent = it->phys_descent = 0;
30998 it->pixel_width = 0;
30999 it->nglyphs = 0;
31000 return;
31001 }
31002
31003 img = IMAGE_FROM_ID (it->f, it->image_id);
31004
31005 prepare_image_for_display (it->f, img);
31006
31007 slice.x = slice.y = 0;
31008 slice.width = img->width;
31009 slice.height = img->height;
31010
31011 if (FIXNUMP (it->slice.x))
31012 slice.x = XFIXNUM (it->slice.x);
31013 else if (FLOATP (it->slice.x))
31014 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31015
31016 if (FIXNUMP (it->slice.y))
31017 slice.y = XFIXNUM (it->slice.y);
31018 else if (FLOATP (it->slice.y))
31019 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31020
31021 if (FIXNUMP (it->slice.width))
31022 slice.width = XFIXNUM (it->slice.width);
31023 else if (FLOATP (it->slice.width))
31024 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31025
31026 if (FIXNUMP (it->slice.height))
31027 slice.height = XFIXNUM (it->slice.height);
31028 else if (FLOATP (it->slice.height))
31029 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31030
31031 if (slice.x >= img->width)
31032 slice.x = img->width;
31033 if (slice.y >= img->height)
31034 slice.y = img->height;
31035 if (slice.x + slice.width >= img->width)
31036 slice.width = img->width - slice.x;
31037 if (slice.y + slice.height > img->height)
31038 slice.height = img->height - slice.y;
31039
31040 if (slice.width == 0 || slice.height == 0)
31041 return;
31042
31043 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31044
31045 it->descent = slice.height - glyph_ascent;
31046 if (slice.y == 0)
31047 it->descent += img->vmargin;
31048 if (slice.y + slice.height == img->height)
31049 it->descent += img->vmargin;
31050 it->phys_descent = it->descent;
31051
31052 it->pixel_width = slice.width;
31053 if (slice.x == 0)
31054 it->pixel_width += img->hmargin;
31055 if (slice.x + slice.width == img->width)
31056 it->pixel_width += img->hmargin;
31057
31058
31059
31060 if (it->descent < 0)
31061 it->descent = 0;
31062
31063 it->nglyphs = 1;
31064
31065 if (face->box != FACE_NO_BOX)
31066 {
31067
31068
31069 if (face->box_horizontal_line_width > 0)
31070 {
31071 if (slice.y == 0)
31072 it->ascent += face->box_horizontal_line_width;
31073 if (slice.y + slice.height == img->height)
31074 it->descent += face->box_horizontal_line_width;
31075 }
31076
31077 if (face->box_vertical_line_width > 0)
31078 {
31079 if (it->start_of_box_run_p && slice.x == 0)
31080 it->pixel_width += face->box_vertical_line_width;
31081 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31082 it->pixel_width += face->box_vertical_line_width;
31083 }
31084 }
31085
31086 take_vertical_position_into_account (it);
31087
31088
31089
31090 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31091 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31092 {
31093 it->pixel_width -= crop;
31094 slice.width -= crop;
31095 }
31096
31097 if (it->glyph_row)
31098 {
31099 struct glyph *glyph;
31100 enum glyph_row_area area = it->area;
31101
31102 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31103 if (it->glyph_row->reversed_p)
31104 {
31105 struct glyph *g;
31106
31107
31108 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31109 g[1] = *g;
31110 glyph = it->glyph_row->glyphs[it->area];
31111 }
31112 if (glyph < it->glyph_row->glyphs[area + 1])
31113 {
31114 glyph->charpos = CHARPOS (it->position);
31115 glyph->object = it->object;
31116 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31117 glyph->ascent = glyph_ascent;
31118 glyph->descent = it->descent;
31119 glyph->voffset = it->voffset;
31120 glyph->type = IMAGE_GLYPH;
31121 glyph->avoid_cursor_p = it->avoid_cursor_p;
31122 glyph->multibyte_p = it->multibyte_p;
31123 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31124 {
31125
31126
31127 glyph->right_box_line_p = it->start_of_box_run_p;
31128 glyph->left_box_line_p = it->end_of_box_run_p;
31129 }
31130 else
31131 {
31132 glyph->left_box_line_p = it->start_of_box_run_p;
31133 glyph->right_box_line_p = it->end_of_box_run_p;
31134 }
31135 glyph->overlaps_vertically_p = false;
31136 glyph->padding_p = false;
31137 glyph->glyph_not_available_p = false;
31138 glyph->face_id = it->face_id;
31139 glyph->u.img_id = img->id;
31140 glyph->slice.img = slice;
31141 glyph->font_type = FONT_TYPE_UNKNOWN;
31142 if (it->bidi_p)
31143 {
31144 glyph->resolved_level = it->bidi_it.resolved_level;
31145 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31146 glyph->bidi_type = it->bidi_it.type;
31147 }
31148 ++it->glyph_row->used[area];
31149 }
31150 else
31151 IT_EXPAND_MATRIX_WIDTH (it, area);
31152 }
31153 }
31154
31155 static void
31156 produce_xwidget_glyph (struct it *it)
31157 {
31158 #ifdef HAVE_XWIDGETS
31159 struct xwidget *xw;
31160 int glyph_ascent, crop;
31161 eassert (it->what == IT_XWIDGET);
31162
31163 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31164
31165 prepare_face_for_display (it->f, face);
31166
31167 xw = it->xwidget;
31168 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31169 it->descent = xw->height/2;
31170 it->phys_descent = it->descent;
31171 it->pixel_width = xw->width;
31172
31173
31174 if (it->descent < 0)
31175 it->descent = 0;
31176
31177 it->nglyphs = 1;
31178
31179 if (face->box != FACE_NO_BOX)
31180 {
31181 if (face->box_horizontal_line_width > 0)
31182 {
31183 it->ascent += face->box_horizontal_line_width;
31184 it->descent += face->box_horizontal_line_width;
31185 }
31186
31187 if (face->box_vertical_line_width > 0)
31188 {
31189 if (it->start_of_box_run_p)
31190 it->pixel_width += face->box_vertical_line_width;
31191 it->pixel_width += face->box_vertical_line_width;
31192 }
31193 }
31194
31195 take_vertical_position_into_account (it);
31196
31197
31198
31199 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31200 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31201 it->pixel_width -= crop;
31202
31203 if (it->glyph_row)
31204 {
31205 enum glyph_row_area area = it->area;
31206 struct glyph *glyph
31207 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31208
31209 if (it->glyph_row->reversed_p)
31210 {
31211 struct glyph *g;
31212
31213
31214 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31215 g[1] = *g;
31216 glyph = it->glyph_row->glyphs[it->area];
31217 }
31218 if (glyph < it->glyph_row->glyphs[area + 1])
31219 {
31220 glyph->charpos = CHARPOS (it->position);
31221 glyph->object = it->object;
31222 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31223 glyph->ascent = glyph_ascent;
31224 glyph->descent = it->descent;
31225 glyph->voffset = it->voffset;
31226 glyph->type = XWIDGET_GLYPH;
31227 glyph->avoid_cursor_p = it->avoid_cursor_p;
31228 glyph->multibyte_p = it->multibyte_p;
31229 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31230 {
31231
31232
31233 glyph->right_box_line_p = it->start_of_box_run_p;
31234 glyph->left_box_line_p = it->end_of_box_run_p;
31235 }
31236 else
31237 {
31238 glyph->left_box_line_p = it->start_of_box_run_p;
31239 glyph->right_box_line_p = it->end_of_box_run_p;
31240 }
31241 glyph->overlaps_vertically_p = 0;
31242 glyph->padding_p = 0;
31243 glyph->glyph_not_available_p = 0;
31244 glyph->face_id = it->face_id;
31245 glyph->u.xwidget = it->xwidget->xwidget_id;
31246 glyph->font_type = FONT_TYPE_UNKNOWN;
31247 if (it->bidi_p)
31248 {
31249 glyph->resolved_level = it->bidi_it.resolved_level;
31250 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31251 glyph->bidi_type = it->bidi_it.type;
31252 }
31253 ++it->glyph_row->used[area];
31254 }
31255 else
31256 IT_EXPAND_MATRIX_WIDTH (it, area);
31257 }
31258 #endif
31259 }
31260
31261
31262
31263
31264
31265 static void
31266 append_stretch_glyph (struct it *it, Lisp_Object object,
31267 int width, int height, int ascent)
31268 {
31269 struct glyph *glyph;
31270 enum glyph_row_area area = it->area;
31271
31272 eassert (ascent >= 0 && ascent <= height);
31273
31274 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31275 if (glyph < it->glyph_row->glyphs[area + 1])
31276 {
31277
31278
31279 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31280 {
31281 struct glyph *g;
31282
31283
31284 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31285 g[1] = *g;
31286 glyph = it->glyph_row->glyphs[area];
31287
31288
31289
31290
31291
31292
31293
31294
31295
31296
31297
31298
31299
31300
31301
31302 if (it->current_x < it->first_visible_x)
31303 width -= it->first_visible_x - it->current_x;
31304 eassert (width > 0);
31305 }
31306 glyph->charpos = CHARPOS (it->position);
31307 glyph->object = object;
31308
31309
31310 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31311 glyph->ascent = ascent;
31312 glyph->descent = height - ascent;
31313 glyph->voffset = it->voffset;
31314 glyph->type = STRETCH_GLYPH;
31315 glyph->avoid_cursor_p = it->avoid_cursor_p;
31316 glyph->multibyte_p = it->multibyte_p;
31317 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31318 {
31319
31320
31321 glyph->right_box_line_p = it->start_of_box_run_p;
31322 glyph->left_box_line_p = it->end_of_box_run_p;
31323 }
31324 else
31325 {
31326 glyph->left_box_line_p = it->start_of_box_run_p;
31327 glyph->right_box_line_p = it->end_of_box_run_p;
31328 }
31329 glyph->overlaps_vertically_p = false;
31330 glyph->padding_p = false;
31331 glyph->glyph_not_available_p = false;
31332 glyph->face_id = it->face_id;
31333 glyph->u.stretch.ascent = ascent;
31334 glyph->u.stretch.height = height;
31335 glyph->slice.img = null_glyph_slice;
31336 glyph->font_type = FONT_TYPE_UNKNOWN;
31337 if (it->bidi_p)
31338 {
31339 glyph->resolved_level = it->bidi_it.resolved_level;
31340 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31341 glyph->bidi_type = it->bidi_it.type;
31342 }
31343 else
31344 {
31345 glyph->resolved_level = 0;
31346 glyph->bidi_type = UNKNOWN_BT;
31347 }
31348 ++it->glyph_row->used[area];
31349 }
31350 else
31351 IT_EXPAND_MATRIX_WIDTH (it, area);
31352 }
31353
31354 #endif
31355
31356
31357
31358
31359
31360
31361
31362
31363
31364
31365
31366
31367
31368
31369
31370
31371
31372
31373
31374
31375
31376
31377
31378
31379
31380
31381
31382
31383
31384
31385
31386
31387 void
31388 produce_stretch_glyph (struct it *it)
31389 {
31390
31391 Lisp_Object prop, plist;
31392 int width = 0, height = 0, align_to = -1;
31393 bool zero_width_ok_p = false;
31394 double tem;
31395 struct font *font = NULL;
31396
31397 #ifdef HAVE_WINDOW_SYSTEM
31398 int ascent = 0;
31399 bool zero_height_ok_p = false;
31400 struct face *face = NULL;
31401
31402 if (FRAME_WINDOW_P (it->f))
31403 {
31404 face = FACE_FROM_ID (it->f, it->face_id);
31405 font = face->font ? face->font : FRAME_FONT (it->f);
31406 prepare_face_for_display (it->f, face);
31407 }
31408 #endif
31409
31410
31411 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31412 plist = XCDR (it->object);
31413
31414
31415 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31416 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31417 {
31418
31419 zero_width_ok_p = true;
31420 width = (int)tem;
31421 }
31422 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31423 {
31424
31425
31426
31427 struct it it2;
31428 Lisp_Object object =
31429 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31430 unsigned char *p = (STRINGP (object)
31431 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31432 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31433 bool multibyte_p =
31434 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31435
31436 it2 = *it;
31437 if (multibyte_p)
31438 {
31439 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31440 #ifdef HAVE_WINDOW_SYSTEM
31441 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31442 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31443 IT_CHARPOS (*it),
31444 STRINGP (object)? object : Qnil);
31445 #endif
31446 }
31447 else
31448 {
31449 it2.c = it2.char_to_display = *p, it2.len = 1;
31450 if (! ASCII_CHAR_P (it2.c))
31451 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31452 }
31453
31454 it2.glyph_row = NULL;
31455 it2.what = IT_CHARACTER;
31456 PRODUCE_GLYPHS (&it2);
31457 width = NUMVAL (prop) * it2.pixel_width;
31458 }
31459 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31460 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31461 &align_to))
31462 {
31463 int x = it->current_x + it->continuation_lines_width;
31464 int x0 = x;
31465
31466 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31467 {
31468 x -= it->lnum_pixel_width;
31469
31470 if (x + it->stretch_adjust >= it->first_visible_x)
31471 x += it->stretch_adjust;
31472 }
31473
31474 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31475 align_to = (align_to < 0
31476 ? 0
31477 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31478 else if (align_to < 0)
31479 align_to = window_box_left_offset (it->w, TEXT_AREA);
31480 width = max (0, (int)tem + align_to - x);
31481
31482 int next_x = x + width;
31483 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31484 {
31485
31486
31487 if (x < it->first_visible_x)
31488 {
31489 next_x -= it->first_visible_x - x;
31490 it->stretch_adjust = it->first_visible_x - x;
31491 }
31492 else
31493 next_x -= it->stretch_adjust;
31494 }
31495 width = next_x - x0;
31496 zero_width_ok_p = true;
31497 }
31498 else
31499
31500 width = FRAME_COLUMN_WIDTH (it->f);
31501
31502 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31503 width = 1;
31504
31505 #ifdef HAVE_WINDOW_SYSTEM
31506
31507 if (FRAME_WINDOW_P (it->f))
31508 {
31509 int default_height = normal_char_height (font, ' ');
31510
31511 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31512 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31513 {
31514 height = (int)tem;
31515 zero_height_ok_p = true;
31516 }
31517 else if (prop = plist_get (plist, QCrelative_height),
31518 NUMVAL (prop) > 0)
31519 height = default_height * NUMVAL (prop);
31520 else
31521 height = default_height;
31522
31523 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31524 height = 1;
31525
31526
31527
31528
31529 if (prop = plist_get (plist, QCascent),
31530 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31531 ascent = height * NUMVAL (prop) / 100.0;
31532 else if (!NILP (prop)
31533 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31534 ascent = min (max (0, (int)tem), height);
31535 else
31536 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31537 }
31538 else
31539 #endif
31540 height = 1;
31541
31542 if (width > 0
31543 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31544 && it->current_x + width > it->last_visible_x)
31545 {
31546 width = it->last_visible_x - it->current_x;
31547 #ifdef HAVE_WINDOW_SYSTEM
31548
31549
31550 width -= FRAME_WINDOW_P (it->f);
31551 #endif
31552 }
31553
31554 if (width > 0 && height > 0 && it->glyph_row)
31555 {
31556 Lisp_Object o_object = it->object;
31557 Lisp_Object object =
31558 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31559 int n = width;
31560
31561 if (!STRINGP (object))
31562 object = it->w->contents;
31563 #ifdef HAVE_WINDOW_SYSTEM
31564 if (FRAME_WINDOW_P (it->f))
31565 append_stretch_glyph (it, object, width, height, ascent);
31566 else
31567 #endif
31568 {
31569 it->object = object;
31570 it->char_to_display = ' ';
31571 it->pixel_width = it->len = 1;
31572 while (n--)
31573 tty_append_glyph (it);
31574 it->object = o_object;
31575 }
31576 }
31577
31578 it->pixel_width = width;
31579 #ifdef HAVE_WINDOW_SYSTEM
31580 if (FRAME_WINDOW_P (it->f))
31581 {
31582 it->ascent = it->phys_ascent = ascent;
31583 it->descent = it->phys_descent = height - it->ascent;
31584 it->nglyphs = width > 0 && height > 0;
31585 take_vertical_position_into_account (it);
31586 }
31587 else
31588 #endif
31589 it->nglyphs = width;
31590 }
31591
31592
31593
31594
31595
31596
31597
31598 static void
31599 produce_special_glyphs (struct it *it, enum display_element_type what)
31600 {
31601 struct it temp_it;
31602 Lisp_Object gc;
31603 GLYPH glyph;
31604
31605 temp_it = *it;
31606 temp_it.object = Qnil;
31607 memset (&temp_it.current, 0, sizeof temp_it.current);
31608
31609 if (what == IT_CONTINUATION)
31610 {
31611
31612 if (it->bidi_it.paragraph_dir == R2L)
31613 SET_GLYPH_FROM_CHAR (glyph, '/');
31614 else
31615 SET_GLYPH_FROM_CHAR (glyph, '\\');
31616 if (it->dp
31617 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31618 {
31619
31620 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31621 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31622 }
31623 }
31624 else if (what == IT_TRUNCATION)
31625 {
31626
31627 SET_GLYPH_FROM_CHAR (glyph, '$');
31628 if (it->dp
31629 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31630 {
31631
31632 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31633 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31634 }
31635 }
31636 else
31637 emacs_abort ();
31638
31639 #ifdef HAVE_WINDOW_SYSTEM
31640
31641
31642
31643
31644
31645 if (FRAME_WINDOW_P (temp_it.f)
31646
31647
31648
31649 && temp_it.glyph_row
31650
31651
31652
31653 && temp_it.glyph_row->used[TEXT_AREA] > 0
31654 && (temp_it.glyph_row->reversed_p
31655 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31656 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31657 {
31658 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31659
31660 if (stretch_width > 0)
31661 {
31662 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31663 struct font *font =
31664 face->font ? face->font : FRAME_FONT (temp_it.f);
31665 int stretch_ascent =
31666 (((temp_it.ascent + temp_it.descent)
31667 * FONT_BASE (font)) / FONT_HEIGHT (font));
31668
31669 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31670 temp_it.ascent + temp_it.descent,
31671 stretch_ascent);
31672 }
31673 }
31674 #endif
31675
31676 temp_it.dp = NULL;
31677 temp_it.what = IT_CHARACTER;
31678 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31679 temp_it.face_id = GLYPH_FACE (glyph);
31680 temp_it.len = CHAR_BYTES (temp_it.c);
31681
31682 PRODUCE_GLYPHS (&temp_it);
31683 it->pixel_width = temp_it.pixel_width;
31684 it->nglyphs = temp_it.nglyphs;
31685 }
31686
31687
31688
31689
31690
31691
31692
31693
31694
31695 static void
31696 pad_mode_line (struct it *it, bool mode_line_p)
31697 {
31698 struct it temp_it;
31699 GLYPH glyph;
31700
31701 eassert (!FRAME_WINDOW_P (it->f));
31702 temp_it = *it;
31703 temp_it.object = Qnil;
31704 memset (&temp_it.current, 0, sizeof temp_it.current);
31705
31706 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31707
31708 temp_it.dp = NULL;
31709 temp_it.what = IT_CHARACTER;
31710 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31711 temp_it.face_id = GLYPH_FACE (glyph);
31712 temp_it.len = CHAR_BYTES (temp_it.c);
31713
31714 PRODUCE_GLYPHS (&temp_it);
31715 it->pixel_width = temp_it.pixel_width;
31716 it->nglyphs = temp_it.nglyphs;
31717 }
31718
31719 #ifdef HAVE_WINDOW_SYSTEM
31720
31721
31722
31723
31724
31725
31726
31727
31728
31729 static Lisp_Object
31730 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31731 int boff, bool override)
31732 {
31733 Lisp_Object face_name = Qnil;
31734 int ascent, descent, height;
31735
31736 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31737 return val;
31738
31739 if (CONSP (val))
31740 {
31741 face_name = XCAR (val);
31742 val = XCDR (val);
31743 if (!NUMBERP (val))
31744 val = make_fixnum (1);
31745 if (NILP (face_name))
31746 {
31747 height = it->ascent + it->descent;
31748 goto scale;
31749 }
31750 }
31751
31752 if (NILP (face_name))
31753 {
31754 font = FRAME_FONT (it->f);
31755 boff = FRAME_BASELINE_OFFSET (it->f);
31756 }
31757 else if (EQ (face_name, Qt))
31758 {
31759 override = false;
31760 }
31761 else
31762 {
31763 int face_id;
31764 struct face *face;
31765
31766 face_id = lookup_named_face (it->w, it->f, face_name, false);
31767 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31768 if (face == NULL || ((font = face->font) == NULL))
31769 return make_fixnum (-1);
31770 boff = font->baseline_offset;
31771 if (font->vertical_centering)
31772 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31773 }
31774
31775 normal_char_ascent_descent (font, -1, &ascent, &descent);
31776
31777 if (override)
31778 {
31779 it->override_ascent = ascent;
31780 it->override_descent = descent;
31781 it->override_boff = boff;
31782 }
31783
31784 height = ascent + descent;
31785
31786 scale:
31787
31788 if (FLOATP (val))
31789 height = (int)(XFLOAT_DATA (val) * height);
31790 else if (INTEGERP (val))
31791 {
31792 intmax_t v;
31793 if (integer_to_intmax (val, &v))
31794 height *= v;
31795 }
31796
31797 return make_fixnum (height);
31798 }
31799
31800
31801
31802
31803
31804
31805
31806
31807
31808
31809
31810
31811
31812
31813 static void
31814 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31815 short upper_xoff, short upper_yoff,
31816 short lower_xoff, short lower_yoff)
31817 {
31818 struct glyph *glyph;
31819 enum glyph_row_area area = it->area;
31820
31821 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31822 if (glyph < it->glyph_row->glyphs[area + 1])
31823 {
31824
31825
31826 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31827 {
31828 struct glyph *g;
31829
31830
31831 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31832 g[1] = *g;
31833 glyph = it->glyph_row->glyphs[area];
31834 }
31835 glyph->charpos = CHARPOS (it->position);
31836 glyph->object = it->object;
31837 eassert (it->pixel_width <= SHRT_MAX);
31838 glyph->pixel_width = it->pixel_width;
31839 glyph->ascent = it->ascent;
31840 glyph->descent = it->descent;
31841 glyph->voffset = it->voffset;
31842 glyph->type = GLYPHLESS_GLYPH;
31843 glyph->u.glyphless.method = it->glyphless_method;
31844 glyph->u.glyphless.for_no_font = for_no_font;
31845 glyph->u.glyphless.len = len;
31846 glyph->u.glyphless.ch = it->c;
31847 glyph->slice.glyphless.upper_xoff = upper_xoff;
31848 glyph->slice.glyphless.upper_yoff = upper_yoff;
31849 glyph->slice.glyphless.lower_xoff = lower_xoff;
31850 glyph->slice.glyphless.lower_yoff = lower_yoff;
31851 glyph->avoid_cursor_p = it->avoid_cursor_p;
31852 glyph->multibyte_p = it->multibyte_p;
31853 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31854 {
31855
31856
31857 glyph->right_box_line_p = it->start_of_box_run_p;
31858 glyph->left_box_line_p = it->end_of_box_run_p;
31859 }
31860 else
31861 {
31862 glyph->left_box_line_p = it->start_of_box_run_p;
31863 glyph->right_box_line_p = it->end_of_box_run_p;
31864 }
31865 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31866 || it->phys_descent > it->descent);
31867 glyph->padding_p = false;
31868 glyph->glyph_not_available_p = false;
31869 glyph->face_id = face_id;
31870 glyph->font_type = FONT_TYPE_UNKNOWN;
31871 if (it->bidi_p)
31872 {
31873 glyph->resolved_level = it->bidi_it.resolved_level;
31874 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31875 glyph->bidi_type = it->bidi_it.type;
31876 }
31877 ++it->glyph_row->used[area];
31878 }
31879 else
31880 IT_EXPAND_MATRIX_WIDTH (it, area);
31881 }
31882
31883
31884
31885
31886
31887
31888
31889
31890
31891
31892
31893 static void
31894 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
31895 {
31896 int face_id;
31897 struct face *face;
31898 struct font *font;
31899 int base_width, base_height, width, height;
31900 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
31901 int len;
31902
31903
31904
31905 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
31906 font = face->font ? face->font : FRAME_FONT (it->f);
31907 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
31908 it->ascent += font->baseline_offset;
31909 it->descent -= font->baseline_offset;
31910 base_height = it->ascent + it->descent;
31911 base_width = font->average_width;
31912
31913 face_id = merge_glyphless_glyph_face (it);
31914
31915 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
31916 {
31917 it->pixel_width = THIN_SPACE_WIDTH;
31918 len = 0;
31919 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31920 }
31921 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
31922 {
31923 width = CHARACTER_WIDTH (it->c);
31924 if (width == 0)
31925 width = 1;
31926 else if (width > 4)
31927 width = 4;
31928 it->pixel_width = base_width * width;
31929 len = 0;
31930 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31931 }
31932 else
31933 {
31934 char buf[7];
31935 const char *str;
31936 unsigned int code[6];
31937 int upper_len;
31938 int ascent, descent;
31939 struct font_metrics metrics_upper, metrics_lower;
31940
31941 face = FACE_FROM_ID (it->f, face_id);
31942 font = face->font ? face->font : FRAME_FONT (it->f);
31943 prepare_face_for_display (it->f, face);
31944
31945 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
31946 {
31947 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
31948 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
31949 if (CONSP (acronym))
31950 acronym = XCAR (acronym);
31951 str = STRINGP (acronym) ? SSDATA (acronym) : "";
31952 }
31953 else
31954 {
31955 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
31956 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
31957 str = buf;
31958 }
31959 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
31960 code[len] = font->driver->encode_char (font, str[len]);
31961 upper_len = (len + 1) / 2;
31962 font->driver->text_extents (font, code, upper_len,
31963 &metrics_upper);
31964 font->driver->text_extents (font, code + upper_len, len - upper_len,
31965 &metrics_lower);
31966
31967
31968
31969
31970 width = max (metrics_upper.width, metrics_lower.width) + 4;
31971 upper_xoff = lower_xoff = 2;
31972 if (base_width >= width)
31973 {
31974
31975 it->pixel_width = base_width;
31976 lower_xoff = base_width - 2 - metrics_lower.width;
31977 }
31978 else
31979 {
31980
31981 it->pixel_width = width;
31982 if (metrics_upper.width >= metrics_lower.width)
31983 lower_xoff = (width - metrics_lower.width) / 2;
31984 else
31985 upper_xoff = (width - metrics_upper.width) / 2;
31986 }
31987
31988
31989
31990 height = (metrics_upper.ascent + metrics_upper.descent
31991 + metrics_lower.ascent + metrics_lower.descent) + 5;
31992
31993
31994
31995
31996
31997
31998
31999
32000 ascent = - (it->descent - (base_height + height + 1) / 2);
32001 descent = it->descent - (base_height - height) / 2;
32002 lower_yoff = descent - 2 - metrics_lower.descent;
32003 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32004 - metrics_upper.descent);
32005
32006 if (height > base_height)
32007 {
32008 it->ascent = ascent;
32009 it->descent = descent;
32010 }
32011 }
32012
32013 it->phys_ascent = it->ascent;
32014 it->phys_descent = it->descent;
32015 if (it->glyph_row)
32016 append_glyphless_glyph (it, face_id, for_no_font, len,
32017 upper_xoff, upper_yoff,
32018 lower_xoff, lower_yoff);
32019 it->nglyphs = 1;
32020 take_vertical_position_into_account (it);
32021 }
32022
32023
32024
32025
32026
32027 #define IT_APPLY_FACE_BOX(it, face) \
32028 do { \
32029 if (face->box != FACE_NO_BOX) \
32030 { \
32031 int thick = face->box_horizontal_line_width; \
32032 if (thick > 0) \
32033 { \
32034 it->ascent += thick; \
32035 it->descent += thick; \
32036 } \
32037 \
32038 thick = face->box_vertical_line_width; \
32039 if (thick > 0) \
32040 { \
32041 if (it->start_of_box_run_p) \
32042 it->pixel_width += thick; \
32043 if (it->end_of_box_run_p) \
32044 it->pixel_width += thick; \
32045 } \
32046 } \
32047 } while (false)
32048
32049
32050
32051
32052
32053
32054 void
32055 gui_produce_glyphs (struct it *it)
32056 {
32057 int extra_line_spacing = it->extra_line_spacing;
32058
32059 it->glyph_not_available_p = false;
32060
32061 if (it->what == IT_CHARACTER)
32062 {
32063 unsigned char2b;
32064 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32065 struct font *font = face->font;
32066 struct font_metrics *pcm = NULL;
32067 int boff;
32068
32069 if (font == NULL)
32070 {
32071
32072
32073
32074 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32075
32076 eassert (it->what == IT_GLYPHLESS);
32077 produce_glyphless_glyph (it, true,
32078 STRINGP (acronym) ? acronym : Qnil);
32079 goto done;
32080 }
32081
32082 boff = font->baseline_offset;
32083 if (font->vertical_centering)
32084 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32085
32086 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32087 {
32088 it->nglyphs = 1;
32089
32090 if (it->override_ascent >= 0)
32091 {
32092 it->ascent = it->override_ascent;
32093 it->descent = it->override_descent;
32094 boff = it->override_boff;
32095 }
32096 else
32097 {
32098 it->ascent = FONT_BASE (font) + boff;
32099 it->descent = FONT_DESCENT (font) - boff;
32100 }
32101
32102 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32103 {
32104 pcm = get_per_char_metric (font, &char2b);
32105 if (pcm->width == 0
32106 && pcm->rbearing == 0 && pcm->lbearing == 0)
32107 pcm = NULL;
32108 }
32109
32110 if (pcm)
32111 {
32112 it->phys_ascent = pcm->ascent + boff;
32113 it->phys_descent = pcm->descent - boff;
32114 it->pixel_width = pcm->width;
32115
32116
32117 if (it->override_ascent < 0)
32118 {
32119 if (FONT_TOO_HIGH (font))
32120 {
32121 it->ascent = it->phys_ascent;
32122 it->descent = it->phys_descent;
32123
32124
32125 if (it->ascent < 0)
32126 it->ascent = 0;
32127 if (it->descent < 0)
32128 it->descent = 0;
32129 }
32130 }
32131 }
32132 else
32133 {
32134 it->glyph_not_available_p = true;
32135 it->phys_ascent = it->ascent;
32136 it->phys_descent = it->descent;
32137 it->pixel_width = font->space_width;
32138 }
32139
32140 if (it->constrain_row_ascent_descent_p)
32141 {
32142 if (it->descent > it->max_descent)
32143 {
32144 it->ascent += it->descent - it->max_descent;
32145 it->descent = it->max_descent;
32146 }
32147 if (it->ascent > it->max_ascent)
32148 {
32149 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32150 it->ascent = it->max_ascent;
32151 }
32152 it->phys_ascent = min (it->phys_ascent, it->ascent);
32153 it->phys_descent = min (it->phys_descent, it->descent);
32154 extra_line_spacing = 0;
32155 }
32156
32157
32158
32159 bool stretched_p
32160 = it->char_to_display == ' ' && !NILP (it->space_width);
32161 if (stretched_p)
32162 it->pixel_width *= XFLOATINT (it->space_width);
32163
32164 IT_APPLY_FACE_BOX(it, face);
32165
32166
32167
32168 if (face->overline_p)
32169 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32170
32171 if (it->constrain_row_ascent_descent_p)
32172 {
32173 if (it->ascent > it->max_ascent)
32174 it->ascent = it->max_ascent;
32175 if (it->descent > it->max_descent)
32176 it->descent = it->max_descent;
32177 }
32178
32179 take_vertical_position_into_account (it);
32180
32181
32182 if (it->glyph_row)
32183 {
32184 if (stretched_p)
32185 {
32186
32187
32188 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32189 / FONT_HEIGHT (font));
32190 append_stretch_glyph (it, it->object, it->pixel_width,
32191 it->ascent + it->descent, ascent);
32192 }
32193 else
32194 append_glyph (it);
32195
32196
32197
32198
32199 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32200 it->glyph_row->contains_overlapping_glyphs_p = true;
32201 }
32202 if (! stretched_p && it->pixel_width == 0)
32203
32204
32205 it->pixel_width = 1;
32206 }
32207 else if (it->char_to_display == '\n')
32208 {
32209
32210
32211
32212
32213 Lisp_Object height;
32214 Lisp_Object total_height = Qnil;
32215
32216 it->override_ascent = -1;
32217 it->pixel_width = 0;
32218 it->nglyphs = 0;
32219
32220 height = get_it_property (it, Qline_height);
32221
32222 if (CONSP (height)
32223 && CONSP (XCDR (height))
32224 && NILP (XCDR (XCDR (height))))
32225 {
32226 total_height = XCAR (XCDR (height));
32227 height = XCAR (height);
32228 }
32229 height = calc_line_height_property (it, height, font, boff, true);
32230
32231 if (it->override_ascent >= 0)
32232 {
32233 it->ascent = it->override_ascent;
32234 it->descent = it->override_descent;
32235 boff = it->override_boff;
32236 }
32237 else
32238 {
32239 if (FONT_TOO_HIGH (font))
32240 {
32241 it->ascent = font->pixel_size + boff - 1;
32242 it->descent = -boff + 1;
32243 if (it->descent < 0)
32244 it->descent = 0;
32245 }
32246 else
32247 {
32248 it->ascent = FONT_BASE (font) + boff;
32249 it->descent = FONT_DESCENT (font) - boff;
32250 }
32251 }
32252
32253 if (EQ (height, Qt))
32254 {
32255 if (it->descent > it->max_descent)
32256 {
32257 it->ascent += it->descent - it->max_descent;
32258 it->descent = it->max_descent;
32259 }
32260 if (it->ascent > it->max_ascent)
32261 {
32262 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32263 it->ascent = it->max_ascent;
32264 }
32265 it->phys_ascent = min (it->phys_ascent, it->ascent);
32266 it->phys_descent = min (it->phys_descent, it->descent);
32267 it->constrain_row_ascent_descent_p = true;
32268 extra_line_spacing = 0;
32269 }
32270 else
32271 {
32272 Lisp_Object spacing;
32273
32274 it->phys_ascent = it->ascent;
32275 it->phys_descent = it->descent;
32276
32277 if ((it->max_ascent > 0 || it->max_descent > 0)
32278 && face->box != FACE_NO_BOX
32279 && face->box_horizontal_line_width > 0)
32280 {
32281 it->ascent += face->box_horizontal_line_width;
32282 it->descent += face->box_horizontal_line_width;
32283 }
32284 if (!NILP (height)
32285 && XFIXNUM (height) > it->ascent + it->descent)
32286 it->ascent = XFIXNUM (height) - it->descent;
32287
32288 if (!NILP (total_height))
32289 spacing = calc_line_height_property (it, total_height, font,
32290 boff, false);
32291 else
32292 {
32293 spacing = get_it_property (it, Qline_spacing);
32294 spacing = calc_line_height_property (it, spacing, font,
32295 boff, false);
32296 }
32297 if (FIXNUMP (spacing))
32298 {
32299 extra_line_spacing = XFIXNUM (spacing);
32300 if (!NILP (total_height))
32301 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32302 }
32303 }
32304 }
32305 else
32306 {
32307 if (font->space_width > 0)
32308 {
32309 int tab_width = it->tab_width * font->space_width;
32310 int x = it->current_x + it->continuation_lines_width;
32311 int x0 = x;
32312
32313 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32314 {
32315 x -= it->lnum_pixel_width;
32316
32317 if (x + it->stretch_adjust >= it->first_visible_x)
32318 x += it->stretch_adjust;
32319 }
32320
32321 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32322
32323
32324
32325
32326 if (next_tab_x - x < font->space_width)
32327 next_tab_x += tab_width;
32328 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32329 {
32330 next_tab_x += it->lnum_pixel_width;
32331
32332
32333 if (x < it->first_visible_x)
32334 {
32335 next_tab_x -= it->first_visible_x - x;
32336 it->stretch_adjust = it->first_visible_x - x;
32337 }
32338 else
32339 next_tab_x -= it->stretch_adjust;
32340 }
32341
32342 it->pixel_width = next_tab_x - x0;
32343 it->nglyphs = 1;
32344 if (FONT_TOO_HIGH (font))
32345 {
32346 if (get_char_glyph_code (' ', font, &char2b))
32347 {
32348 pcm = get_per_char_metric (font, &char2b);
32349 if (pcm->width == 0
32350 && pcm->rbearing == 0 && pcm->lbearing == 0)
32351 pcm = NULL;
32352 }
32353
32354 if (pcm)
32355 {
32356 it->ascent = pcm->ascent + boff;
32357 it->descent = pcm->descent - boff;
32358 }
32359 else
32360 {
32361 it->ascent = font->pixel_size + boff - 1;
32362 it->descent = -boff + 1;
32363 }
32364 if (it->ascent < 0)
32365 it->ascent = 0;
32366 if (it->descent < 0)
32367 it->descent = 0;
32368 }
32369 else
32370 {
32371 it->ascent = FONT_BASE (font) + boff;
32372 it->descent = FONT_DESCENT (font) - boff;
32373 }
32374 it->phys_ascent = it->ascent;
32375 it->phys_descent = it->descent;
32376
32377 if (it->glyph_row)
32378 {
32379 append_stretch_glyph (it, it->object, it->pixel_width,
32380 it->ascent + it->descent, it->ascent);
32381 }
32382 }
32383 else
32384 {
32385 it->pixel_width = 0;
32386 it->nglyphs = 1;
32387 }
32388 }
32389
32390 if (FONT_TOO_HIGH (font))
32391 {
32392 int font_ascent, font_descent;
32393
32394
32395
32396
32397
32398
32399
32400
32401 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32402 it->max_ascent = max (it->max_ascent, font_ascent);
32403 it->max_descent = max (it->max_descent, font_descent);
32404 }
32405
32406 if (it->ascent < 0)
32407 it->ascent = 0;
32408 if (it->descent < 0)
32409 it->descent = 0;
32410 }
32411 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32412 {
32413
32414
32415
32416
32417
32418
32419
32420
32421 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32422 int boff;
32423 struct composition *cmp = composition_table[it->cmp_it.id];
32424 int glyph_len = cmp->glyph_len;
32425 struct font *font = face->font;
32426
32427 it->nglyphs = 1;
32428
32429
32430
32431
32432
32433
32434
32435
32436 if (! cmp->font || cmp->font != font)
32437 {
32438
32439
32440
32441
32442 int font_ascent, font_descent, font_height;
32443
32444 int leftmost, rightmost, lowest, highest;
32445 int lbearing, rbearing;
32446 int i, width, ascent, descent;
32447 int c;
32448 unsigned char2b;
32449 struct font_metrics *pcm;
32450 ptrdiff_t pos;
32451
32452 eassume (0 < glyph_len);
32453 do
32454 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32455 while (c == '\t' && 0 < --glyph_len);
32456
32457 bool right_padded = glyph_len < cmp->glyph_len;
32458 for (i = 0; i < glyph_len; i++)
32459 {
32460 c = COMPOSITION_GLYPH (cmp, i);
32461 if (c != '\t')
32462 break;
32463 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32464 }
32465 bool left_padded = i > 0;
32466
32467 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32468 : IT_CHARPOS (*it));
32469
32470 bool font_not_found_p = font == NULL;
32471 if (font_not_found_p)
32472 {
32473 face = face->ascii_face;
32474 font = face->font;
32475 }
32476 boff = font->baseline_offset;
32477 if (font->vertical_centering)
32478 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32479 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32480 font_ascent += boff;
32481 font_descent -= boff;
32482 font_height = font_ascent + font_descent;
32483
32484 cmp->font = font;
32485
32486 pcm = NULL;
32487 if (! font_not_found_p)
32488 {
32489 get_char_face_and_encoding (it->f, c, it->face_id,
32490 &char2b, false);
32491 pcm = get_per_char_metric (font, &char2b);
32492 }
32493
32494
32495 if (pcm)
32496 {
32497 width = cmp->glyph_len > 0 ? pcm->width : 0;
32498 ascent = pcm->ascent;
32499 descent = pcm->descent;
32500 lbearing = pcm->lbearing;
32501 rbearing = pcm->rbearing;
32502 }
32503 else
32504 {
32505 width = cmp->glyph_len > 0 ? font->space_width : 0;
32506 ascent = FONT_BASE (font);
32507 descent = FONT_DESCENT (font);
32508 lbearing = 0;
32509 rbearing = width;
32510 }
32511
32512 rightmost = width;
32513 leftmost = 0;
32514 lowest = - descent + boff;
32515 highest = ascent + boff;
32516
32517 if (! font_not_found_p
32518 && font->default_ascent
32519 && CHAR_TABLE_P (Vuse_default_ascent)
32520 && !NILP (Faref (Vuse_default_ascent,
32521 make_fixnum (it->char_to_display))))
32522 highest = font->default_ascent + boff;
32523
32524
32525
32526
32527 cmp->offsets[i * 2] = 0;
32528 cmp->offsets[i * 2 + 1] = boff;
32529 cmp->lbearing = lbearing;
32530 cmp->rbearing = rbearing;
32531
32532
32533 for (i++; i < glyph_len; i++)
32534 {
32535 int left, right, btm, top;
32536 int ch = COMPOSITION_GLYPH (cmp, i);
32537 int face_id;
32538 struct face *this_face;
32539
32540 if (ch == '\t')
32541 ch = ' ';
32542 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32543 this_face = FACE_FROM_ID (it->f, face_id);
32544 font = this_face->font;
32545
32546 if (font == NULL)
32547 pcm = NULL;
32548 else
32549 {
32550 get_char_face_and_encoding (it->f, ch, face_id,
32551 &char2b, false);
32552 pcm = get_per_char_metric (font, &char2b);
32553 }
32554 if (! pcm)
32555 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32556 else
32557 {
32558 width = pcm->width;
32559 ascent = pcm->ascent;
32560 descent = pcm->descent;
32561 lbearing = pcm->lbearing;
32562 rbearing = pcm->rbearing;
32563 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32564 {
32565
32566
32567 left = (leftmost + rightmost - width) / 2;
32568 btm = - descent + boff;
32569 if (font->relative_compose
32570 && (! CHAR_TABLE_P (Vignore_relative_composition)
32571 || NILP (Faref (Vignore_relative_composition,
32572 make_fixnum (ch)))))
32573 {
32574
32575 if (- descent >= font->relative_compose)
32576
32577 btm = highest + 1;
32578 else if (ascent <= 0)
32579
32580 btm = lowest - 1 - ascent - descent;
32581 }
32582 }
32583 else
32584 {
32585
32586
32587
32588
32589
32590
32591
32592
32593
32594
32595
32596
32597
32598
32599
32600 int rule = COMPOSITION_RULE (cmp, i);
32601 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32602
32603 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32604 grefx = gref % 3, nrefx = nref % 3;
32605 grefy = gref / 3, nrefy = nref / 3;
32606 if (xoff)
32607 xoff = font_height * (xoff - 128) / 256;
32608 if (yoff)
32609 yoff = font_height * (yoff - 128) / 256;
32610
32611 left = (leftmost
32612 + grefx * (rightmost - leftmost) / 2
32613 - nrefx * width / 2
32614 + xoff);
32615
32616 btm = ((grefy == 0 ? highest
32617 : grefy == 1 ? 0
32618 : grefy == 2 ? lowest
32619 : (highest + lowest) / 2)
32620 - (nrefy == 0 ? ascent + descent
32621 : nrefy == 1 ? descent - boff
32622 : nrefy == 2 ? 0
32623 : (ascent + descent) / 2)
32624 + yoff);
32625 }
32626
32627 cmp->offsets[i * 2] = left;
32628 cmp->offsets[i * 2 + 1] = btm + descent;
32629
32630
32631 if (width > 0)
32632 {
32633 right = left + width;
32634 if (left < leftmost)
32635 leftmost = left;
32636 if (right > rightmost)
32637 rightmost = right;
32638 }
32639 top = btm + descent + ascent;
32640 if (top > highest)
32641 highest = top;
32642 if (btm < lowest)
32643 lowest = btm;
32644
32645 if (cmp->lbearing > left + lbearing)
32646 cmp->lbearing = left + lbearing;
32647 if (cmp->rbearing < left + rbearing)
32648 cmp->rbearing = left + rbearing;
32649 }
32650 }
32651
32652
32653
32654
32655 if (leftmost < 0)
32656 {
32657 for (i = 0; i < cmp->glyph_len; i++)
32658 cmp->offsets[i * 2] -= leftmost;
32659 rightmost -= leftmost;
32660 cmp->lbearing -= leftmost;
32661 cmp->rbearing -= leftmost;
32662 }
32663
32664 if (left_padded && cmp->lbearing < 0)
32665 {
32666 for (i = 0; i < cmp->glyph_len; i++)
32667 cmp->offsets[i * 2] -= cmp->lbearing;
32668 rightmost -= cmp->lbearing;
32669 cmp->rbearing -= cmp->lbearing;
32670 cmp->lbearing = 0;
32671 }
32672 if (right_padded && rightmost < cmp->rbearing)
32673 {
32674 rightmost = cmp->rbearing;
32675 }
32676
32677 cmp->pixel_width = rightmost;
32678 cmp->ascent = highest;
32679 cmp->descent = - lowest;
32680 if (cmp->ascent < font_ascent)
32681 cmp->ascent = font_ascent;
32682 if (cmp->descent < font_descent)
32683 cmp->descent = font_descent;
32684 }
32685
32686 if (it->glyph_row
32687 && (cmp->lbearing < 0
32688 || cmp->rbearing > cmp->pixel_width))
32689 it->glyph_row->contains_overlapping_glyphs_p = true;
32690
32691 it->pixel_width = cmp->pixel_width;
32692 it->ascent = it->phys_ascent = cmp->ascent;
32693 it->descent = it->phys_descent = cmp->descent;
32694 IT_APPLY_FACE_BOX(it, face);
32695
32696
32697
32698 if (face->overline_p)
32699 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32700
32701 take_vertical_position_into_account (it);
32702 if (it->ascent < 0)
32703 it->ascent = 0;
32704 if (it->descent < 0)
32705 it->descent = 0;
32706
32707 if (it->glyph_row && cmp->glyph_len > 0)
32708 append_composite_glyph (it);
32709 }
32710 else if (it->what == IT_COMPOSITION)
32711 {
32712
32713 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32714 Lisp_Object gstring;
32715 struct font_metrics metrics;
32716
32717 it->nglyphs = 1;
32718
32719 gstring = composition_gstring_from_id (it->cmp_it.id);
32720 it->pixel_width
32721 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32722 &metrics);
32723 if (it->pixel_width == 0)
32724 {
32725 it->glyph_not_available_p = true;
32726 it->phys_ascent = it->ascent;
32727 it->phys_descent = it->descent;
32728 it->pixel_width = face->font->space_width;
32729 }
32730 else
32731 {
32732 if (it->glyph_row
32733 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32734 it->glyph_row->contains_overlapping_glyphs_p = true;
32735 it->ascent = it->phys_ascent = metrics.ascent;
32736 it->descent = it->phys_descent = metrics.descent;
32737 }
32738 IT_APPLY_FACE_BOX(it, face);
32739
32740
32741
32742 if (face->overline_p)
32743 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32744 take_vertical_position_into_account (it);
32745 if (it->ascent < 0)
32746 it->ascent = 0;
32747 if (it->descent < 0)
32748 it->descent = 0;
32749
32750 if (it->glyph_row)
32751 append_composite_glyph (it);
32752 }
32753 else if (it->what == IT_GLYPHLESS)
32754 produce_glyphless_glyph (it, false, Qnil);
32755 else if (it->what == IT_IMAGE)
32756 produce_image_glyph (it);
32757 else if (it->what == IT_STRETCH)
32758 produce_stretch_glyph (it);
32759 else if (it->what == IT_XWIDGET)
32760 produce_xwidget_glyph (it);
32761
32762 done:
32763
32764
32765 eassert (it->ascent >= 0 && it->descent >= 0);
32766 if (it->area == TEXT_AREA)
32767 it->current_x += it->pixel_width;
32768
32769 if (extra_line_spacing > 0)
32770 {
32771 it->descent += extra_line_spacing;
32772 if (extra_line_spacing > it->max_extra_line_spacing)
32773 it->max_extra_line_spacing = extra_line_spacing;
32774 }
32775
32776 it->max_ascent = max (it->max_ascent, it->ascent);
32777 it->max_descent = max (it->max_descent, it->descent);
32778 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32779 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32780 }
32781
32782
32783
32784
32785
32786
32787 void
32788 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32789 struct glyph *start, enum glyph_row_area updated_area, int len)
32790 {
32791 int x, hpos, chpos = w->phys_cursor.hpos;
32792
32793 eassert (updated_row);
32794
32795
32796
32797 if (!updated_row->reversed_p && chpos < 0)
32798 chpos = 0;
32799 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32800 chpos = updated_row->used[TEXT_AREA] - 1;
32801
32802 block_input ();
32803
32804
32805
32806 hpos = start - updated_row->glyphs[updated_area];
32807 x = draw_glyphs (w, w->output_cursor.x,
32808 updated_row, updated_area,
32809 hpos, hpos + len,
32810 DRAW_NORMAL_TEXT, 0);
32811
32812
32813 if (updated_area == TEXT_AREA
32814 && w->phys_cursor_on_p
32815 && w->phys_cursor.vpos == w->output_cursor.vpos
32816 && chpos >= hpos
32817 && chpos < hpos + len)
32818 w->phys_cursor_on_p = false;
32819
32820 unblock_input ();
32821
32822
32823 w->output_cursor.hpos += len;
32824 w->output_cursor.x = x;
32825 }
32826
32827
32828
32829
32830
32831 void
32832 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32833 struct glyph *start, enum glyph_row_area updated_area, int len)
32834 {
32835 struct frame *f;
32836 int line_height, shift_by_width, shifted_region_width;
32837 struct glyph_row *row;
32838 struct glyph *glyph;
32839 int frame_x, frame_y;
32840 ptrdiff_t hpos;
32841
32842 eassert (updated_row);
32843 block_input ();
32844 f = XFRAME (WINDOW_FRAME (w));
32845
32846
32847 row = updated_row;
32848 line_height = row->height;
32849
32850
32851 shift_by_width = 0;
32852 for (glyph = start; glyph < start + len; ++glyph)
32853 shift_by_width += glyph->pixel_width;
32854
32855
32856 shifted_region_width = (window_box_width (w, updated_area)
32857 - w->output_cursor.x
32858 - shift_by_width);
32859
32860
32861 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32862 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32863
32864 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32865 line_height, shift_by_width);
32866
32867
32868 hpos = start - row->glyphs[updated_area];
32869 draw_glyphs (w, w->output_cursor.x, row, updated_area,
32870 hpos, hpos + len,
32871 DRAW_NORMAL_TEXT, 0);
32872
32873
32874 w->output_cursor.hpos += len;
32875 w->output_cursor.x += shift_by_width;
32876 unblock_input ();
32877 }
32878
32879
32880
32881
32882
32883
32884
32885
32886
32887
32888 void
32889 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
32890 enum glyph_row_area updated_area, int to_x)
32891 {
32892 struct frame *f;
32893 int max_x, min_y, max_y;
32894 int from_x, from_y, to_y;
32895 struct face *face;
32896
32897 eassert (updated_row);
32898 f = XFRAME (w->frame);
32899 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
32900
32901 if (updated_row->full_width_p)
32902 max_x = (WINDOW_PIXEL_WIDTH (w)
32903 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
32904 else
32905 max_x = window_box_width (w, updated_area);
32906 max_y = window_text_bottom_y (w);
32907
32908
32909
32910 if (to_x == 0)
32911 return;
32912 else if (to_x < 0)
32913 to_x = max_x;
32914 else
32915 to_x = min (to_x, max_x);
32916
32917 to_y = min (max_y, w->output_cursor.y + updated_row->height);
32918
32919
32920 if (!updated_row->full_width_p)
32921 notice_overwritten_cursor (w, updated_area,
32922 w->output_cursor.x, -1,
32923 updated_row->y,
32924 MATRIX_ROW_BOTTOM_Y (updated_row));
32925
32926 from_x = w->output_cursor.x;
32927
32928
32929 if (updated_row->full_width_p)
32930 {
32931 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
32932 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
32933 }
32934 else
32935 {
32936 int area_left = window_box_left (w, updated_area);
32937 from_x += area_left;
32938 to_x += area_left;
32939 }
32940
32941 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
32942 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
32943 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
32944
32945
32946 if (to_x > from_x && to_y > from_y)
32947 {
32948 block_input ();
32949 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
32950 to_x - from_x, to_y - from_y);
32951
32952 if (face && !updated_row->stipple_p)
32953 updated_row->stipple_p = face->stipple;
32954 unblock_input ();
32955 }
32956 }
32957
32958 #endif
32959
32960
32961
32962
32963
32964
32965
32966
32967
32968
32969
32970 static enum text_cursor_kinds
32971 get_specified_cursor_type (Lisp_Object arg, int *width)
32972 {
32973 enum text_cursor_kinds type;
32974
32975 if (NILP (arg))
32976 return NO_CURSOR;
32977
32978 if (EQ (arg, Qbox))
32979 return FILLED_BOX_CURSOR;
32980
32981 if (EQ (arg, Qhollow))
32982 return HOLLOW_BOX_CURSOR;
32983
32984 if (EQ (arg, Qbar))
32985 {
32986 *width = 2;
32987 return BAR_CURSOR;
32988 }
32989
32990 if (EQ (arg, Qhbar))
32991 {
32992 *width = 2;
32993 return HBAR_CURSOR;
32994 }
32995
32996 if (CONSP (arg)
32997 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
32998 {
32999 *width = XFIXNUM (XCDR (arg));
33000
33001 if (EQ (XCAR (arg), Qbox))
33002 return FILLED_BOX_CURSOR;
33003 else if (EQ (XCAR (arg), Qbar))
33004 return BAR_CURSOR;
33005 else if (EQ (XCAR (arg), Qhbar))
33006 return HBAR_CURSOR;
33007 }
33008
33009
33010
33011
33012 type = HOLLOW_BOX_CURSOR;
33013
33014 return type;
33015 }
33016
33017
33018 void
33019 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33020 {
33021 int width = 1;
33022 Lisp_Object tem;
33023
33024 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33025 FRAME_CURSOR_WIDTH (f) = width;
33026
33027
33028
33029 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33030 if (!NILP (tem))
33031 {
33032 FRAME_BLINK_OFF_CURSOR (f)
33033 = get_specified_cursor_type (XCDR (tem), &width);
33034 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33035 }
33036 else
33037 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33038
33039
33040 f->cursor_type_changed = true;
33041 }
33042
33043
33044 #ifdef HAVE_WINDOW_SYSTEM
33045
33046
33047
33048
33049
33050
33051
33052
33053
33054
33055
33056
33057 static enum text_cursor_kinds
33058 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33059 bool *active_cursor)
33060 {
33061 struct frame *f = XFRAME (w->frame);
33062 struct buffer *b = XBUFFER (w->contents);
33063 int cursor_type = DEFAULT_CURSOR;
33064 Lisp_Object alt_cursor;
33065 bool non_selected = false;
33066
33067 *active_cursor = true;
33068
33069
33070 if (cursor_in_echo_area
33071 && FRAME_HAS_MINIBUF_P (f)
33072 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33073 {
33074 if (w == XWINDOW (echo_area_window))
33075 {
33076 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33077 {
33078 *width = FRAME_CURSOR_WIDTH (f);
33079 return FRAME_DESIRED_CURSOR (f);
33080 }
33081 else
33082 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33083 }
33084
33085 *active_cursor = false;
33086 non_selected = true;
33087 }
33088
33089
33090 else if (w != XWINDOW (f->selected_window)
33091 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33092 {
33093 *active_cursor = false;
33094
33095 if (MINI_WINDOW_P (w) &&
33096 (minibuf_level == 0
33097 || is_minibuffer (0, w->contents)))
33098 return NO_CURSOR;
33099
33100 non_selected = true;
33101 }
33102
33103
33104 if (NILP (BVAR (b, cursor_type)))
33105 return NO_CURSOR;
33106
33107
33108 if (EQ (BVAR (b, cursor_type), Qt))
33109 {
33110 cursor_type = FRAME_DESIRED_CURSOR (f);
33111 *width = FRAME_CURSOR_WIDTH (f);
33112 }
33113 else
33114 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33115
33116
33117
33118 if (non_selected)
33119 {
33120 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33121 if (!EQ (Qt, alt_cursor))
33122 return get_specified_cursor_type (alt_cursor, width);
33123
33124 if (cursor_type == FILLED_BOX_CURSOR)
33125 cursor_type = HOLLOW_BOX_CURSOR;
33126 else if (cursor_type == BAR_CURSOR && *width > 1)
33127 --*width;
33128 return cursor_type;
33129 }
33130
33131
33132 if (!w->cursor_off_p)
33133 {
33134 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33135 return NO_CURSOR;
33136 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33137 {
33138 if (cursor_type == FILLED_BOX_CURSOR)
33139 {
33140
33141
33142
33143
33144 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33145 if (img != NULL && IMAGEP (img->spec))
33146 {
33147
33148
33149
33150
33151
33152
33153 if (!img->mask
33154 || (CONSP (BVAR (b, cursor_type))
33155 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33156 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33157 cursor_type = HOLLOW_BOX_CURSOR;
33158 }
33159 }
33160 else if (cursor_type != NO_CURSOR)
33161 {
33162
33163
33164
33165 cursor_type = HOLLOW_BOX_CURSOR;
33166 }
33167 }
33168 return cursor_type;
33169 }
33170
33171
33172
33173
33174 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33175 return get_specified_cursor_type (XCDR (alt_cursor), width);
33176
33177
33178 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33179 {
33180 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33181 return FRAME_BLINK_OFF_CURSOR (f);
33182 }
33183
33184 #if false
33185
33186
33187
33188
33189
33190
33191
33192
33193
33194
33195 if (cursor_type == FILLED_BOX_CURSOR)
33196 return HOLLOW_BOX_CURSOR;
33197
33198 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33199 {
33200 *width = 1;
33201 return cursor_type;
33202 }
33203 #endif
33204
33205 return NO_CURSOR;
33206 }
33207
33208
33209
33210
33211
33212
33213
33214
33215
33216 static void
33217 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33218 int x0, int x1, int y0, int y1)
33219 {
33220 int cx0, cx1, cy0, cy1;
33221 struct glyph_row *row;
33222
33223 if (!w->phys_cursor_on_p)
33224 return;
33225 if (area != TEXT_AREA)
33226 return;
33227
33228 if (w->phys_cursor.vpos < 0
33229 || w->phys_cursor.vpos >= w->current_matrix->nrows
33230 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33231 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33232 return;
33233
33234 if (row->cursor_in_fringe_p)
33235 {
33236 row->cursor_in_fringe_p = false;
33237 draw_fringe_bitmap (w, row, row->reversed_p);
33238 w->phys_cursor_on_p = false;
33239 return;
33240 }
33241
33242 cx0 = w->phys_cursor.x;
33243 cx1 = cx0 + w->phys_cursor_width;
33244 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33245 return;
33246
33247
33248
33249
33250
33251
33252
33253
33254
33255
33256
33257
33258
33259
33260
33261
33262
33263 cy0 = w->phys_cursor.y;
33264 cy1 = cy0 + w->phys_cursor_height;
33265 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33266 return;
33267
33268 w->phys_cursor_on_p = false;
33269 }
33270
33271 #endif
33272
33273
33274
33275
33276
33277
33278 #ifdef HAVE_WINDOW_SYSTEM
33279
33280
33281
33282
33283
33284 void
33285 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33286 enum glyph_row_area area, int overlaps)
33287 {
33288 int i, x;
33289
33290 block_input ();
33291
33292 x = 0;
33293 for (i = 0; i < row->used[area];)
33294 {
33295 if (row->glyphs[area][i].overlaps_vertically_p)
33296 {
33297 int start = i, start_x = x;
33298
33299 do
33300 {
33301 x += row->glyphs[area][i].pixel_width;
33302 ++i;
33303 }
33304 while (i < row->used[area]
33305 && row->glyphs[area][i].overlaps_vertically_p);
33306
33307 draw_glyphs (w, start_x, row, area,
33308 start, i,
33309 DRAW_NORMAL_TEXT, overlaps);
33310 }
33311 else
33312 {
33313 x += row->glyphs[area][i].pixel_width;
33314 ++i;
33315 }
33316 }
33317
33318 unblock_input ();
33319 }
33320
33321
33322
33323
33324
33325
33326 void
33327 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33328 enum draw_glyphs_face hl)
33329 {
33330
33331
33332
33333 if ((row->reversed_p
33334 ? (w->phys_cursor.hpos >= 0)
33335 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33336 {
33337 bool on_p = w->phys_cursor_on_p;
33338 int x1;
33339 int hpos = w->phys_cursor.hpos;
33340
33341
33342
33343
33344 if (!row->reversed_p && hpos < 0)
33345 hpos = 0;
33346 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33347 hpos = row->used[TEXT_AREA] - 1;
33348
33349 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33350 hl, 0);
33351 w->phys_cursor_on_p = on_p;
33352
33353 if (hl == DRAW_CURSOR)
33354 w->phys_cursor_width = x1 - w->phys_cursor.x;
33355
33356
33357
33358 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33359 {
33360 w->phys_cursor_width = x1 - w->phys_cursor.x;
33361
33362 if (row > w->current_matrix->rows
33363 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33364 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33365 OVERLAPS_ERASED_CURSOR);
33366
33367 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33368 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33369 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33370 OVERLAPS_ERASED_CURSOR);
33371 }
33372 }
33373 }
33374
33375
33376
33377
33378 void
33379 erase_phys_cursor (struct window *w)
33380 {
33381 struct frame *f = XFRAME (w->frame);
33382 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33383 int hpos = w->phys_cursor.hpos;
33384 int vpos = w->phys_cursor.vpos;
33385 bool mouse_face_here_p = false;
33386 struct glyph_matrix *active_glyphs = w->current_matrix;
33387 struct glyph_row *cursor_row;
33388 struct glyph *cursor_glyph;
33389 enum draw_glyphs_face hl;
33390
33391
33392
33393 if (w->phys_cursor_type == NO_CURSOR)
33394 goto mark_cursor_off;
33395
33396
33397
33398 if (vpos >= active_glyphs->nrows)
33399 goto mark_cursor_off;
33400
33401
33402
33403 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33404 if (!cursor_row->enabled_p)
33405 goto mark_cursor_off;
33406
33407
33408
33409 cursor_row->visible_height = min (cursor_row->visible_height,
33410 window_text_bottom_y (w) - cursor_row->y);
33411
33412
33413
33414
33415 if (cursor_row->visible_height <= 0)
33416 goto mark_cursor_off;
33417
33418
33419 if (cursor_row->cursor_in_fringe_p)
33420 {
33421 cursor_row->cursor_in_fringe_p = false;
33422 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33423 goto mark_cursor_off;
33424 }
33425
33426
33427
33428
33429
33430
33431 if ((cursor_row->reversed_p
33432 ? (w->phys_cursor.hpos < 0)
33433 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33434 goto mark_cursor_off;
33435
33436
33437
33438
33439 if (!cursor_row->reversed_p && hpos < 0)
33440 hpos = 0;
33441 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33442 hpos = cursor_row->used[TEXT_AREA] - 1;
33443
33444
33445
33446 if (! NILP (hlinfo->mouse_face_window)
33447 && coords_in_mouse_face_p (w, hpos, vpos)
33448
33449
33450
33451 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33452 mouse_face_here_p = true;
33453
33454 #ifdef HAVE_WINDOW_SYSTEM
33455
33456
33457
33458
33459 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33460 {
33461 w->phys_cursor_on_p = false;
33462 w->phys_cursor_type = NO_CURSOR;
33463 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33464 return;
33465 }
33466 #endif
33467
33468
33469 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33470 {
33471 int x, y;
33472 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33473 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33474 int width;
33475
33476 cursor_glyph = get_phys_cursor_glyph (w);
33477 if (cursor_glyph == NULL)
33478 goto mark_cursor_off;
33479
33480 width = cursor_glyph->pixel_width;
33481 x = w->phys_cursor.x;
33482 if (x < 0)
33483 {
33484 width += x;
33485 x = 0;
33486 }
33487 width = min (width, window_box_width (w, TEXT_AREA) - x);
33488 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33489 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33490
33491 if (width > 0)
33492 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33493 }
33494
33495
33496 if (mouse_face_here_p)
33497 hl = DRAW_MOUSE_FACE;
33498 else
33499 hl = DRAW_NORMAL_TEXT;
33500 draw_phys_cursor_glyph (w, cursor_row, hl);
33501
33502 mark_cursor_off:
33503 w->phys_cursor_on_p = false;
33504 w->phys_cursor_type = NO_CURSOR;
33505 }
33506
33507
33508
33509
33510
33511
33512 void
33513 display_and_set_cursor (struct window *w, bool on,
33514 int hpos, int vpos, int x, int y)
33515 {
33516 struct frame *f = XFRAME (w->frame);
33517 int new_cursor_type;
33518 int new_cursor_width UNINIT;
33519 bool active_cursor;
33520 struct glyph_row *glyph_row;
33521 struct glyph *glyph;
33522
33523
33524
33525
33526
33527 if (! FRAME_REDISPLAY_P (f)
33528 || vpos >= w->current_matrix->nrows
33529 || hpos >= w->current_matrix->matrix_w)
33530 return;
33531
33532
33533 if (!on && !w->phys_cursor_on_p)
33534 return;
33535
33536 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33537
33538
33539 if (!glyph_row->enabled_p)
33540 {
33541 w->phys_cursor_on_p = false;
33542 return;
33543 }
33544
33545
33546
33547
33548
33549
33550
33551
33552
33553 if (FRAME_GARBAGED_P (f))
33554 {
33555 if (on)
33556 {
33557 w->phys_cursor.x = x;
33558 w->phys_cursor.y = glyph_row->y;
33559 w->phys_cursor.hpos = hpos;
33560 w->phys_cursor.vpos = vpos;
33561 }
33562 return;
33563 }
33564
33565 glyph = NULL;
33566 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33567 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33568
33569 eassert (input_blocked_p ());
33570
33571
33572 new_cursor_type = get_window_cursor_type (w, glyph,
33573 &new_cursor_width, &active_cursor);
33574
33575
33576
33577
33578 if (w->phys_cursor_on_p
33579 && (!on
33580 || w->phys_cursor.x != x
33581 || w->phys_cursor.y != y
33582
33583
33584
33585 || hpos < 0
33586 || new_cursor_type != w->phys_cursor_type
33587 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33588 && new_cursor_width != w->phys_cursor_width)))
33589 erase_phys_cursor (w);
33590
33591
33592
33593
33594
33595
33596 if (on)
33597 {
33598 w->phys_cursor_ascent = glyph_row->ascent;
33599 w->phys_cursor_height = glyph_row->height;
33600
33601
33602
33603 w->phys_cursor.x = x;
33604 w->phys_cursor.y = glyph_row->y;
33605 w->phys_cursor.hpos = hpos;
33606 w->phys_cursor.vpos = vpos;
33607 }
33608
33609 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33610 new_cursor_type, new_cursor_width,
33611 on, active_cursor);
33612 }
33613
33614
33615
33616
33617
33618 static void
33619 update_window_cursor (struct window *w, bool on)
33620 {
33621
33622
33623 if (w->current_matrix)
33624 {
33625 int hpos = w->phys_cursor.hpos;
33626 int vpos = w->phys_cursor.vpos;
33627 struct glyph_row *row;
33628
33629 if (vpos >= w->current_matrix->nrows
33630 || hpos >= w->current_matrix->matrix_w)
33631 return;
33632
33633 row = MATRIX_ROW (w->current_matrix, vpos);
33634
33635
33636
33637
33638 if (!row->reversed_p && hpos < 0)
33639 hpos = 0;
33640 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33641 hpos = row->used[TEXT_AREA] - 1;
33642
33643 block_input ();
33644 display_and_set_cursor (w, on, hpos, vpos,
33645 w->phys_cursor.x, w->phys_cursor.y);
33646 unblock_input ();
33647 }
33648 }
33649
33650
33651
33652
33653
33654 static void
33655 update_cursor_in_window_tree (struct window *w, bool on_p)
33656 {
33657 while (w)
33658 {
33659 if (WINDOWP (w->contents))
33660 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33661 else
33662 update_window_cursor (w, on_p);
33663
33664 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33665 }
33666 }
33667
33668
33669
33670
33671
33672
33673 void
33674 gui_update_cursor (struct frame *f, bool on_p)
33675 {
33676 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33677 }
33678
33679
33680
33681
33682
33683
33684
33685 void
33686 gui_clear_cursor (struct window *w)
33687 {
33688 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33689 update_window_cursor (w, false);
33690 }
33691
33692 #endif
33693
33694
33695
33696 static void
33697 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33698 int start_hpos, int end_hpos,
33699 enum draw_glyphs_face draw)
33700 {
33701 #ifdef HAVE_WINDOW_SYSTEM
33702 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33703 {
33704 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33705 return;
33706 }
33707 #endif
33708
33709 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33710 }
33711
33712
33713
33714 static void
33715 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33716 {
33717
33718
33719 if (!WINDOWP (hlinfo->mouse_face_window))
33720 return;
33721
33722 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33723 struct frame *f = XFRAME (WINDOW_FRAME (w));
33724
33725
33726 if (f != hlinfo->mouse_face_mouse_frame)
33727 return;
33728
33729 if (
33730
33731 w->current_matrix != NULL
33732
33733 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33734
33735
33736 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33737 {
33738 bool phys_cursor_on_p = w->phys_cursor_on_p;
33739 #ifdef HAVE_WINDOW_SYSTEM
33740 int mouse_off = 0;
33741 #endif
33742 struct glyph_row *row, *first, *last;
33743
33744 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33745 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33746
33747 for (row = first; row <= last && row->enabled_p; ++row)
33748 {
33749 int start_hpos, end_hpos, start_x;
33750
33751
33752 if (row == first)
33753 {
33754
33755
33756
33757
33758 if (!row->reversed_p)
33759 {
33760 start_hpos = hlinfo->mouse_face_beg_col;
33761 start_x = hlinfo->mouse_face_beg_x;
33762 }
33763 else if (row == last)
33764 {
33765 start_hpos = hlinfo->mouse_face_end_col;
33766 start_x = hlinfo->mouse_face_end_x;
33767 }
33768 else
33769 {
33770 start_hpos = 0;
33771 start_x = 0;
33772 }
33773 }
33774 else if (row->reversed_p && row == last)
33775 {
33776 start_hpos = hlinfo->mouse_face_end_col;
33777 start_x = hlinfo->mouse_face_end_x;
33778 }
33779 else
33780 {
33781 start_hpos = 0;
33782 start_x = 0;
33783 }
33784
33785 if (row == last)
33786 {
33787 if (!row->reversed_p)
33788 end_hpos = hlinfo->mouse_face_end_col;
33789 else if (row == first)
33790 end_hpos = hlinfo->mouse_face_beg_col;
33791 else
33792 {
33793 end_hpos = row->used[TEXT_AREA];
33794 if (draw == DRAW_NORMAL_TEXT)
33795 row->fill_line_p = true;
33796 }
33797 }
33798 else if (row->reversed_p && row == first)
33799 end_hpos = hlinfo->mouse_face_beg_col;
33800 else
33801 {
33802 end_hpos = row->used[TEXT_AREA];
33803 if (draw == DRAW_NORMAL_TEXT)
33804 row->fill_line_p = true;
33805 }
33806
33807 if (end_hpos > start_hpos)
33808 {
33809 draw_row_with_mouse_face (w, start_x, row,
33810 start_hpos, end_hpos, draw);
33811
33812 row->mouse_face_p
33813 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33814 }
33815 #ifdef HAVE_WINDOW_SYSTEM
33816
33817 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33818
33819
33820 && !w->pseudo_window_p
33821 && draw == DRAW_MOUSE_FACE)
33822 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33823 #endif
33824 }
33825
33826
33827
33828 if (FRAME_WINDOW_P (f)
33829 && phys_cursor_on_p && !w->phys_cursor_on_p)
33830 {
33831 #ifdef HAVE_WINDOW_SYSTEM
33832 int hpos = w->phys_cursor.hpos;
33833 int old_phys_cursor_x = w->phys_cursor.x;
33834
33835
33836
33837
33838 if (!row->reversed_p && hpos < 0)
33839 hpos = 0;
33840 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33841 hpos = row->used[TEXT_AREA] - 1;
33842
33843 block_input ();
33844 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33845 w->phys_cursor.x + mouse_off,
33846 w->phys_cursor.y);
33847
33848
33849 w->phys_cursor.x = old_phys_cursor_x;
33850 unblock_input ();
33851 #endif
33852 }
33853 }
33854
33855 #ifdef HAVE_WINDOW_SYSTEM
33856
33857 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33858 {
33859 if (draw == DRAW_NORMAL_TEXT
33860 #ifndef HAVE_EXT_TOOL_BAR
33861 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33862 #endif
33863 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33864 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33865 else
33866 if (draw == DRAW_MOUSE_FACE)
33867 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
33868 else
33869 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
33870 }
33871 #endif
33872 }
33873
33874
33875
33876
33877
33878
33879 bool
33880 clear_mouse_face (Mouse_HLInfo *hlinfo)
33881 {
33882 bool cleared
33883 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
33884 if (cleared)
33885 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
33886 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
33887 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
33888 hlinfo->mouse_face_window = Qnil;
33889 hlinfo->mouse_face_overlay = Qnil;
33890 return cleared;
33891 }
33892
33893
33894
33895 static bool
33896 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33897 {
33898 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
33899
33900
33901 if (!(WINDOWP (hlinfo->mouse_face_window)
33902 && XWINDOW (hlinfo->mouse_face_window) == w))
33903 return false;
33904 if (vpos < hlinfo->mouse_face_beg_row
33905 || vpos > hlinfo->mouse_face_end_row)
33906 return false;
33907 if (vpos > hlinfo->mouse_face_beg_row
33908 && vpos < hlinfo->mouse_face_end_row)
33909 return true;
33910
33911 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
33912 {
33913 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33914 {
33915 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
33916 return true;
33917 }
33918 else if ((vpos == hlinfo->mouse_face_beg_row
33919 && hpos >= hlinfo->mouse_face_beg_col)
33920 || (vpos == hlinfo->mouse_face_end_row
33921 && hpos < hlinfo->mouse_face_end_col))
33922 return true;
33923 }
33924 else
33925 {
33926 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33927 {
33928 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
33929 return true;
33930 }
33931 else if ((vpos == hlinfo->mouse_face_beg_row
33932 && hpos <= hlinfo->mouse_face_beg_col)
33933 || (vpos == hlinfo->mouse_face_end_row
33934 && hpos > hlinfo->mouse_face_end_col))
33935 return true;
33936 }
33937 return false;
33938 }
33939
33940
33941
33942
33943
33944 bool
33945 cursor_in_mouse_face_p (struct window *w)
33946 {
33947 int vpos = w->phys_cursor.vpos;
33948
33949
33950
33951 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33952 return false;
33953
33954 int hpos = w->phys_cursor.hpos;
33955 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33956
33957
33958
33959
33960 if (!row->reversed_p && hpos < 0)
33961 hpos = 0;
33962 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33963 hpos = row->used[TEXT_AREA] - 1;
33964
33965 return coords_in_mouse_face_p (w, hpos, vpos);
33966 }
33967
33968
33969
33970
33971
33972
33973
33974
33975
33976 static void
33977 rows_from_pos_range (struct window *w,
33978 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
33979 Lisp_Object disp_string,
33980 struct glyph_row **start, struct glyph_row **end)
33981 {
33982 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33983 int last_y = window_text_bottom_y (w);
33984 struct glyph_row *row;
33985
33986 *start = NULL;
33987 *end = NULL;
33988
33989 while (!first->enabled_p
33990 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
33991 first++;
33992
33993
33994 for (row = first;
33995 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
33996 row++)
33997 {
33998
33999
34000
34001 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34002 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34003
34004
34005
34006
34007 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34008 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34009 && !row->ends_at_zv_p
34010 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34011 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34012 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34013 && !row->ends_at_zv_p
34014 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34015 {
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025
34026 struct glyph *g = row->glyphs[TEXT_AREA];
34027 struct glyph *e = g + row->used[TEXT_AREA];
34028
34029 while (g < e)
34030 {
34031 if (((BUFFERP (g->object) || NILP (g->object))
34032 && start_charpos <= g->charpos && g->charpos < end_charpos)
34033
34034
34035 || EQ (g->object, disp_string))
34036 *start = row;
34037 g++;
34038 }
34039 if (*start)
34040 break;
34041 }
34042 }
34043
34044
34045 if (!*start
34046
34047
34048 && !(row->enabled_p
34049 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34050 row = first;
34051 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34052 {
34053 struct glyph_row *next = row + 1;
34054 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34055
34056 if (!next->enabled_p
34057 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34058
34059
34060
34061 || (start_charpos < next_start
34062 && end_charpos < next_start)
34063 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34064 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34065 && !next->ends_at_zv_p
34066 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34067 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34068 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34069 && !next->ends_at_zv_p
34070 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34071 {
34072 *end = row;
34073 break;
34074 }
34075 else
34076 {
34077
34078
34079
34080 struct glyph *g = next->glyphs[TEXT_AREA];
34081 struct glyph *s = g;
34082 struct glyph *e = g + next->used[TEXT_AREA];
34083
34084 while (g < e)
34085 {
34086 if (((BUFFERP (g->object) || NILP (g->object))
34087 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34088
34089
34090
34091
34092
34093 || (((!next->reversed_p && g == s)
34094 || (next->reversed_p && g == e - 1))
34095 && (g->charpos == end_charpos
34096
34097
34098 || (g->charpos == -1
34099 && !row->ends_at_zv_p
34100 && next_start == end_charpos)))))
34101
34102
34103 || EQ (g->object, disp_string))
34104 break;
34105 g++;
34106 }
34107 if (g == e)
34108 {
34109 *end = row;
34110 break;
34111 }
34112
34113
34114 else if (next->ends_at_zv_p)
34115 {
34116 *end = next;
34117 break;
34118 }
34119 }
34120 }
34121 }
34122
34123
34124
34125
34126
34127
34128
34129
34130
34131
34132 static void
34133 mouse_face_from_buffer_pos (Lisp_Object window,
34134 Mouse_HLInfo *hlinfo,
34135 ptrdiff_t mouse_charpos,
34136 ptrdiff_t start_charpos,
34137 ptrdiff_t end_charpos,
34138 Lisp_Object before_string,
34139 Lisp_Object after_string,
34140 Lisp_Object disp_string)
34141 {
34142 struct window *w = XWINDOW (window);
34143 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34144 struct glyph_row *r1, *r2;
34145 struct glyph *glyph, *end;
34146 ptrdiff_t ignore, pos;
34147 int x;
34148
34149 eassert (NILP (disp_string) || STRINGP (disp_string));
34150 eassert (NILP (before_string) || STRINGP (before_string));
34151 eassert (NILP (after_string) || STRINGP (after_string));
34152
34153
34154 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34155 if (r1 == NULL)
34156 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34157
34158
34159 if (!NILP (before_string) || !NILP (disp_string))
34160 {
34161 struct glyph_row *prev;
34162 while ((prev = r1 - 1, prev >= first)
34163 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34164 && prev->used[TEXT_AREA] > 0)
34165 {
34166 struct glyph *beg = prev->glyphs[TEXT_AREA];
34167 glyph = beg + prev->used[TEXT_AREA];
34168 while (--glyph >= beg && NILP (glyph->object));
34169 if (glyph < beg
34170 || !(EQ (glyph->object, before_string)
34171 || EQ (glyph->object, disp_string)))
34172 break;
34173 r1 = prev;
34174 }
34175 }
34176 if (r2 == NULL)
34177 {
34178 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34179 hlinfo->mouse_face_past_end = true;
34180 }
34181 else if (!NILP (after_string))
34182 {
34183
34184 struct glyph_row *next;
34185 struct glyph_row *last
34186 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34187
34188 for (next = r2 + 1;
34189 next <= last
34190 && next->used[TEXT_AREA] > 0
34191 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34192 ++next)
34193 r2 = next;
34194 }
34195
34196
34197
34198
34199
34200 if (r1->y > r2->y)
34201 {
34202 struct glyph_row *tem = r2;
34203
34204 r2 = r1;
34205 r1 = tem;
34206 }
34207
34208 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34209 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34210
34211
34212
34213
34214
34215
34216
34217
34218
34219
34220
34221 if (!r1->reversed_p)
34222 {
34223
34224
34225 glyph = r1->glyphs[TEXT_AREA];
34226 end = glyph + r1->used[TEXT_AREA];
34227 x = r1->x;
34228
34229
34230 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34231 for (; glyph < end
34232 && NILP (glyph->object)
34233 && glyph->charpos < 0;
34234 ++glyph)
34235 x += glyph->pixel_width;
34236
34237
34238
34239
34240 for (; glyph < end
34241 && !NILP (glyph->object)
34242 && !EQ (glyph->object, disp_string)
34243 && !(BUFFERP (glyph->object)
34244 && (glyph->charpos >= start_charpos
34245 && glyph->charpos < end_charpos));
34246 ++glyph)
34247 {
34248
34249
34250
34251 if (EQ (glyph->object, before_string))
34252 {
34253 pos = string_buffer_position (before_string,
34254 start_charpos);
34255
34256
34257 if (!pos || (pos >= start_charpos && pos < end_charpos))
34258 break;
34259 }
34260 else if (EQ (glyph->object, after_string))
34261 {
34262 pos = string_buffer_position (after_string, end_charpos);
34263 if (!pos || (pos >= start_charpos && pos < end_charpos))
34264 break;
34265 }
34266 x += glyph->pixel_width;
34267 }
34268 hlinfo->mouse_face_beg_x = x;
34269 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34270 }
34271 else
34272 {
34273
34274
34275 struct glyph *g;
34276
34277 end = r1->glyphs[TEXT_AREA] - 1;
34278 glyph = end + r1->used[TEXT_AREA];
34279
34280
34281 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34282 for (; glyph > end
34283 && NILP (glyph->object)
34284 && glyph->charpos < 0;
34285 --glyph)
34286 ;
34287
34288
34289
34290
34291 for (; glyph > end
34292 && !NILP (glyph->object)
34293 && !EQ (glyph->object, disp_string)
34294 && !(BUFFERP (glyph->object)
34295 && (glyph->charpos >= start_charpos
34296 && glyph->charpos < end_charpos));
34297 --glyph)
34298 {
34299
34300
34301
34302 if (EQ (glyph->object, before_string))
34303 {
34304 pos = string_buffer_position (before_string, start_charpos);
34305
34306
34307 if (!pos || (pos >= start_charpos && pos < end_charpos))
34308 break;
34309 }
34310 else if (EQ (glyph->object, after_string))
34311 {
34312 pos = string_buffer_position (after_string, end_charpos);
34313 if (!pos || (pos >= start_charpos && pos < end_charpos))
34314 break;
34315 }
34316 }
34317
34318 glyph++;
34319 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34320 x += g->pixel_width;
34321 hlinfo->mouse_face_beg_x = x;
34322 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34323 }
34324
34325
34326
34327
34328 if (r2 != r1)
34329 {
34330 if (!r2->reversed_p)
34331 {
34332 glyph = r2->glyphs[TEXT_AREA];
34333 end = glyph + r2->used[TEXT_AREA];
34334 x = r2->x;
34335 }
34336 else
34337 {
34338 end = r2->glyphs[TEXT_AREA] - 1;
34339 glyph = end + r2->used[TEXT_AREA];
34340 }
34341 }
34342
34343 if (!r2->reversed_p)
34344 {
34345
34346
34347
34348 while (end > glyph
34349 && NILP ((end - 1)->object))
34350 --end;
34351
34352
34353
34354
34355 for (--end;
34356 end > glyph
34357 && !NILP (end->object)
34358 && !EQ (end->object, disp_string)
34359 && !(BUFFERP (end->object)
34360 && (end->charpos >= start_charpos
34361 && end->charpos < end_charpos));
34362 --end)
34363 {
34364
34365
34366
34367 if (EQ (end->object, before_string))
34368 {
34369 pos = string_buffer_position (before_string, start_charpos);
34370 if (!pos || (pos >= start_charpos && pos < end_charpos))
34371 break;
34372 }
34373 else if (EQ (end->object, after_string))
34374 {
34375 pos = string_buffer_position (after_string, end_charpos);
34376 if (!pos || (pos >= start_charpos && pos < end_charpos))
34377 break;
34378 }
34379 }
34380
34381 for (; glyph <= end; ++glyph)
34382 x += glyph->pixel_width;
34383
34384 hlinfo->mouse_face_end_x = x;
34385 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34386 }
34387 else
34388 {
34389
34390
34391
34392 x = r2->x;
34393 end++;
34394 while (end < glyph
34395 && NILP (end->object))
34396 {
34397 x += end->pixel_width;
34398 ++end;
34399 }
34400
34401
34402
34403
34404 for ( ;
34405 end < glyph
34406 && !NILP (end->object)
34407 && !EQ (end->object, disp_string)
34408 && !(BUFFERP (end->object)
34409 && (end->charpos >= start_charpos
34410 && end->charpos < end_charpos));
34411 ++end)
34412 {
34413
34414
34415
34416 if (EQ (end->object, before_string))
34417 {
34418 pos = string_buffer_position (before_string, start_charpos);
34419 if (!pos || (pos >= start_charpos && pos < end_charpos))
34420 break;
34421 }
34422 else if (EQ (end->object, after_string))
34423 {
34424 pos = string_buffer_position (after_string, end_charpos);
34425 if (!pos || (pos >= start_charpos && pos < end_charpos))
34426 break;
34427 }
34428 x += end->pixel_width;
34429 }
34430
34431
34432
34433
34434
34435 if (end == glyph
34436 && BUFFERP (end->object)
34437 && (end->charpos < start_charpos
34438 || end->charpos >= end_charpos))
34439 {
34440 x += end->pixel_width;
34441 ++end;
34442 }
34443 hlinfo->mouse_face_end_x = x;
34444 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34445 }
34446
34447 hlinfo->mouse_face_window = window;
34448 hlinfo->mouse_face_face_id
34449 = face_at_buffer_position (w, mouse_charpos, &ignore,
34450 mouse_charpos + 1,
34451 !hlinfo->mouse_face_hidden, -1, 0);
34452 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34453 }
34454
34455
34456
34457
34458
34459 #if false
34460
34461
34462
34463
34464
34465
34466
34467
34468
34469
34470
34471
34472
34473
34474
34475
34476 static bool
34477 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34478 int *hpos, int *vpos, int *x, int *y, bool right_p)
34479 {
34480 int yb = window_text_bottom_y (w);
34481 struct glyph_row *r;
34482 struct glyph *best_glyph = NULL;
34483 struct glyph_row *best_row = NULL;
34484 int best_x = 0;
34485
34486 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34487 r->enabled_p && r->y < yb;
34488 ++r)
34489 {
34490 struct glyph *g = r->glyphs[TEXT_AREA];
34491 struct glyph *e = g + r->used[TEXT_AREA];
34492 int gx;
34493
34494 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34495 if (EQ (g->object, object))
34496 {
34497 if (g->charpos == pos)
34498 {
34499 best_glyph = g;
34500 best_x = gx;
34501 best_row = r;
34502 goto found;
34503 }
34504 else if (best_glyph == NULL
34505 || ((eabs (g->charpos - pos)
34506 < eabs (best_glyph->charpos - pos))
34507 && (right_p
34508 ? g->charpos < pos
34509 : g->charpos > pos)))
34510 {
34511 best_glyph = g;
34512 best_x = gx;
34513 best_row = r;
34514 }
34515 }
34516 }
34517
34518 found:
34519
34520 if (best_glyph)
34521 {
34522 *x = best_x;
34523 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34524
34525 if (right_p)
34526 {
34527 *x += best_glyph->pixel_width;
34528 ++*hpos;
34529 }
34530
34531 *y = best_row->y;
34532 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34533 }
34534
34535 return best_glyph != NULL;
34536 }
34537 #endif
34538
34539
34540
34541
34542
34543
34544 static void
34545 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34546 Lisp_Object object,
34547 ptrdiff_t startpos, ptrdiff_t endpos)
34548 {
34549 int yb = window_text_bottom_y (w);
34550 struct glyph_row *r;
34551 struct glyph *g, *e;
34552 int gx;
34553 bool found = false;
34554
34555
34556
34557
34558 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34559 r->enabled_p && r->y < yb;
34560 ++r)
34561 {
34562 if (!r->reversed_p)
34563 {
34564 g = r->glyphs[TEXT_AREA];
34565 e = g + r->used[TEXT_AREA];
34566 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34567 if (EQ (g->object, object)
34568 && startpos <= g->charpos && g->charpos < endpos)
34569 {
34570 hlinfo->mouse_face_beg_row
34571 = MATRIX_ROW_VPOS (r, w->current_matrix);
34572 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34573 hlinfo->mouse_face_beg_x = gx;
34574 found = true;
34575 break;
34576 }
34577 }
34578 else
34579 {
34580 struct glyph *g1;
34581
34582 e = r->glyphs[TEXT_AREA];
34583 g = e + r->used[TEXT_AREA];
34584 for ( ; g > e; --g)
34585 if (EQ ((g-1)->object, object)
34586 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34587 {
34588 hlinfo->mouse_face_beg_row
34589 = MATRIX_ROW_VPOS (r, w->current_matrix);
34590 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34591 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34592 gx += g1->pixel_width;
34593 hlinfo->mouse_face_beg_x = gx;
34594 found = true;
34595 break;
34596 }
34597 }
34598 if (found)
34599 break;
34600 }
34601
34602 if (!found)
34603 return;
34604
34605
34606
34607 for (++r; r->enabled_p && r->y < yb; ++r)
34608 {
34609 g = r->glyphs[TEXT_AREA];
34610 e = g + r->used[TEXT_AREA];
34611 found = false;
34612 for ( ; g < e; ++g)
34613 if (EQ (g->object, object)
34614 && startpos <= g->charpos && g->charpos < endpos)
34615 {
34616 found = true;
34617 break;
34618 }
34619 if (!found)
34620 break;
34621 }
34622
34623
34624 r--;
34625
34626
34627 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34628
34629
34630
34631 if (!r->reversed_p)
34632 {
34633 g = r->glyphs[TEXT_AREA];
34634 e = g + r->used[TEXT_AREA];
34635 for ( ; e > g; --e)
34636 if (EQ ((e-1)->object, object)
34637 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34638 break;
34639 hlinfo->mouse_face_end_col = e - g;
34640
34641 for (gx = r->x; g < e; ++g)
34642 gx += g->pixel_width;
34643 hlinfo->mouse_face_end_x = gx;
34644 }
34645 else
34646 {
34647 e = r->glyphs[TEXT_AREA];
34648 g = e + r->used[TEXT_AREA];
34649 for (gx = r->x ; e < g; ++e)
34650 {
34651 if (EQ (e->object, object)
34652 && startpos <= e->charpos && e->charpos < endpos)
34653 break;
34654 gx += e->pixel_width;
34655 }
34656 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34657 hlinfo->mouse_face_end_x = gx;
34658 }
34659 }
34660
34661 #ifdef HAVE_WINDOW_SYSTEM
34662
34663
34664
34665 static bool
34666 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34667 {
34668 if (!CONSP (hot_spot))
34669 return false;
34670
34671 if (EQ (XCAR (hot_spot), Qrect))
34672 {
34673
34674 Lisp_Object rect = XCDR (hot_spot);
34675 Lisp_Object tem;
34676 if (!CONSP (rect))
34677 return false;
34678 if (!CONSP (XCAR (rect)))
34679 return false;
34680 if (!CONSP (XCDR (rect)))
34681 return false;
34682 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34683 return false;
34684 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34685 return false;
34686 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34687 return false;
34688 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34689 return false;
34690 return true;
34691 }
34692 else if (EQ (XCAR (hot_spot), Qcircle))
34693 {
34694
34695 Lisp_Object circ = XCDR (hot_spot);
34696 Lisp_Object lr, lx0, ly0;
34697 if (CONSP (circ)
34698 && CONSP (XCAR (circ))
34699 && (lr = XCDR (circ), NUMBERP (lr))
34700 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34701 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34702 {
34703 double r = XFLOATINT (lr);
34704 double dx = XFIXNUM (lx0) - x;
34705 double dy = XFIXNUM (ly0) - y;
34706 return (dx * dx + dy * dy <= r * r);
34707 }
34708 }
34709 else if (EQ (XCAR (hot_spot), Qpoly))
34710 {
34711
34712 if (VECTORP (XCDR (hot_spot)))
34713 {
34714 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34715 Lisp_Object *poly = v->contents;
34716 ptrdiff_t n = v->header.size;
34717 ptrdiff_t i;
34718 bool inside = false;
34719 Lisp_Object lx, ly;
34720 int x0, y0;
34721
34722
34723 if (n < 6 || n & 1)
34724 return false;
34725
34726
34727
34728
34729
34730 if ((lx = poly[n-2], !FIXNUMP (lx))
34731 || (ly = poly[n-1], !FIXNUMP (lx)))
34732 return false;
34733 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34734 for (i = 0; i < n; i += 2)
34735 {
34736 int x1 = x0, y1 = y0;
34737 if ((lx = poly[i], !FIXNUMP (lx))
34738 || (ly = poly[i+1], !FIXNUMP (ly)))
34739 return false;
34740 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34741
34742
34743 if (x0 >= x)
34744 {
34745 if (x1 >= x)
34746 continue;
34747 }
34748 else if (x1 < x)
34749 continue;
34750 if (y > y0 && y > y1)
34751 continue;
34752 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34753 inside = !inside;
34754 }
34755 return inside;
34756 }
34757 }
34758 return false;
34759 }
34760
34761 Lisp_Object
34762 find_hot_spot (Lisp_Object map, int x, int y)
34763 {
34764 while (CONSP (map))
34765 {
34766 if (CONSP (XCAR (map))
34767 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34768 return XCAR (map);
34769 map = XCDR (map);
34770 }
34771
34772 return Qnil;
34773 }
34774
34775 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34776 3, 3, 0,
34777 doc:
34778
34779
34780
34781
34782
34783
34784
34785
34786 )
34787 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34788 {
34789 if (NILP (map))
34790 return Qnil;
34791
34792 CHECK_FIXNUM (x);
34793 CHECK_FIXNUM (y);
34794
34795 return find_hot_spot (map,
34796 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34797 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34798 }
34799 #endif
34800
34801
34802
34803 static void
34804 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34805 {
34806 #ifdef HAVE_WINDOW_SYSTEM
34807 if (!FRAME_WINDOW_P (f))
34808 return;
34809
34810
34811 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34812 || EQ (track_mouse, Qdrag_source))
34813 return;
34814
34815 if (!NILP (pointer))
34816 {
34817 if (EQ (pointer, Qarrow))
34818 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34819 else if (EQ (pointer, Qhand))
34820 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34821 else if (EQ (pointer, Qtext))
34822 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34823 else if (EQ (pointer, intern ("hdrag")))
34824 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34825 else if (EQ (pointer, intern ("nhdrag")))
34826 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34827 # ifdef HAVE_X_WINDOWS
34828 else if (EQ (pointer, intern ("vdrag")))
34829 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34830 # endif
34831 else if (EQ (pointer, intern ("hourglass")))
34832 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34833 else if (EQ (pointer, Qmodeline))
34834 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34835 else
34836 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34837 }
34838
34839 if (cursor != No_Cursor)
34840 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34841 #endif
34842 }
34843
34844
34845
34846
34847
34848
34849
34850 static void
34851 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34852 enum window_part area)
34853 {
34854 struct window *w = XWINDOW (window);
34855 struct frame *f = XFRAME (w->frame);
34856 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34857 Emacs_Cursor cursor = No_Cursor;
34858 Lisp_Object pointer = Qnil;
34859 int dx, dy, width, height;
34860 ptrdiff_t charpos;
34861 Lisp_Object string, object = Qnil;
34862 Lisp_Object pos UNINIT;
34863 Lisp_Object mouse_face;
34864 int original_x_pixel = x;
34865 struct glyph * glyph = NULL, * row_start_glyph = NULL;
34866 struct glyph_row *row UNINIT;
34867
34868 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
34869 {
34870 int x0;
34871 struct glyph *end;
34872
34873
34874
34875 string = mode_line_string (w, area, &x, &y, &charpos,
34876 &object, &dx, &dy, &width, &height);
34877
34878 row = (area == ON_MODE_LINE
34879 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
34880 : (area == ON_TAB_LINE
34881 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
34882 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
34883
34884
34885 if (row->mode_line_p && row->enabled_p)
34886 {
34887 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
34888 end = glyph + row->used[TEXT_AREA];
34889
34890 for (x0 = original_x_pixel;
34891 glyph < end && x0 >= glyph->pixel_width;
34892 ++glyph)
34893 x0 -= glyph->pixel_width;
34894
34895 if (glyph >= end)
34896 glyph = NULL;
34897 }
34898 }
34899 else
34900 {
34901 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
34902
34903
34904 string = marginal_area_string (w, area, &x, &y, &charpos,
34905 &object, &dx, &dy, &width, &height);
34906 }
34907
34908 Lisp_Object help = Qnil;
34909
34910 #ifdef HAVE_WINDOW_SYSTEM
34911 if (IMAGEP (object))
34912 {
34913 Lisp_Object image_map, hotspot;
34914 if ((image_map = plist_get (XCDR (object), QCmap),
34915 !NILP (image_map))
34916 && (hotspot = find_hot_spot (image_map, dx, dy),
34917 CONSP (hotspot))
34918 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
34919 {
34920 Lisp_Object plist;
34921
34922
34923
34924
34925 hotspot = XCDR (hotspot);
34926 if (CONSP (hotspot)
34927 && (plist = XCAR (hotspot), CONSP (plist)))
34928 {
34929 pointer = plist_get (plist, Qpointer);
34930 if (NILP (pointer))
34931 pointer = Qhand;
34932 help = plist_get (plist, Qhelp_echo);
34933 if (!NILP (help))
34934 {
34935 help_echo_string = help;
34936 XSETWINDOW (help_echo_window, w);
34937 help_echo_object = w->contents;
34938 help_echo_pos = charpos;
34939 }
34940 }
34941 }
34942 if (NILP (pointer))
34943 pointer = plist_get (XCDR (object), QCpointer);
34944 }
34945 #endif
34946
34947
34948
34949
34950 if (STRINGP (string))
34951 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
34952
34953
34954
34955
34956
34957 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
34958 || area == ON_TAB_LINE)
34959 {
34960
34961
34962 if (NILP (help))
34963 {
34964 if (STRINGP (string))
34965 help = Fget_text_property (pos, Qhelp_echo, string);
34966
34967 if (!NILP (help))
34968 {
34969 help_echo_string = help;
34970 XSETWINDOW (help_echo_window, w);
34971 help_echo_object = string;
34972 help_echo_pos = charpos;
34973 }
34974 else if (area == ON_MODE_LINE
34975 && !NILP (w->mode_line_help_echo))
34976 {
34977 help_echo_string = w->mode_line_help_echo;
34978 XSETWINDOW (help_echo_window, w);
34979 help_echo_object = Qnil;
34980 help_echo_pos = -1;
34981 }
34982 }
34983
34984 #ifdef HAVE_WINDOW_SYSTEM
34985
34986 if (FRAME_WINDOW_P (f))
34987 {
34988 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
34989 || minibuf_level
34990 || NILP (Vresize_mini_windows));
34991
34992 if (STRINGP (string))
34993 {
34994 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34995
34996 if (NILP (pointer))
34997 pointer = Fget_text_property (pos, Qpointer, string);
34998
34999
35000 if (NILP (pointer)
35001 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35002 || area == ON_TAB_LINE))
35003 {
35004 Lisp_Object map;
35005
35006 map = Fget_text_property (pos, Qlocal_map, string);
35007 if (!KEYMAPP (map))
35008 map = Fget_text_property (pos, Qkeymap, string);
35009 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35010 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35011 }
35012 }
35013 else if (draggable && area == ON_MODE_LINE)
35014 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35015 else if ((area == ON_MODE_LINE
35016 && WINDOW_BOTTOMMOST_P (w)
35017 && !FRAME_HAS_MINIBUF_P (f)
35018 && !NILP (Fframe_parameter
35019 (w->frame, Qdrag_with_mode_line)))
35020 || (((area == ON_HEADER_LINE
35021 && !NILP (Fframe_parameter
35022 (w->frame, Qdrag_with_header_line)))
35023 || (area == ON_TAB_LINE
35024 && !NILP (Fframe_parameter
35025 (w->frame, Qdrag_with_tab_line))))
35026 && WINDOW_TOPMOST_P (w)))
35027 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35028 else
35029 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35030 }
35031 #endif
35032 }
35033
35034
35035 bool mouse_face_shown = false;
35036
35037 if (STRINGP (string))
35038 {
35039 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35040 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35041 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35042 || (area == ON_TAB_LINE))
35043 && glyph)
35044 {
35045 Lisp_Object b, e;
35046
35047 struct glyph * tmp_glyph;
35048
35049 int gpos;
35050 int gseq_length;
35051 int total_pixel_width;
35052 ptrdiff_t begpos, endpos, ignore;
35053
35054 int vpos, hpos;
35055
35056 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35057 Qmouse_face, string, Qnil);
35058 if (NILP (b))
35059 begpos = 0;
35060 else
35061 begpos = XFIXNUM (b);
35062
35063 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35064 if (NILP (e))
35065 endpos = SCHARS (string);
35066 else
35067 endpos = XFIXNUM (e);
35068
35069
35070
35071
35072
35073
35074
35075
35076
35077
35078
35079 tmp_glyph = row_start_glyph;
35080 while (tmp_glyph < glyph
35081 && (!(EQ (tmp_glyph->object, glyph->object)
35082 && begpos <= tmp_glyph->charpos
35083 && tmp_glyph->charpos < endpos)))
35084 tmp_glyph++;
35085 gpos = glyph - tmp_glyph;
35086
35087
35088
35089
35090
35091
35092 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35093 tmp_glyph > glyph
35094 && (!(EQ (tmp_glyph->object, glyph->object)
35095 && begpos <= tmp_glyph->charpos
35096 && tmp_glyph->charpos < endpos));
35097 tmp_glyph--)
35098 ;
35099 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35100
35101
35102
35103 total_pixel_width = 0;
35104 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35105 total_pixel_width += tmp_glyph->pixel_width;
35106
35107
35108
35109
35110 hpos = x - gpos;
35111 vpos = (area == ON_MODE_LINE
35112 ? (w->current_matrix)->nrows - 1
35113 : (area == ON_TAB_LINE
35114 ? 0
35115 : (w->current_matrix->tab_line_p
35116 ? 1
35117 : 0)));
35118
35119
35120
35121 if ( EQ (window, hlinfo->mouse_face_window)
35122 && (!row->reversed_p
35123 ? (hlinfo->mouse_face_beg_col <= hpos
35124 && hpos < hlinfo->mouse_face_end_col)
35125
35126 : (hlinfo->mouse_face_end_col <= hpos
35127 && hpos < hlinfo->mouse_face_beg_col))
35128 && hlinfo->mouse_face_beg_row == vpos )
35129 return;
35130
35131 if (clear_mouse_face (hlinfo))
35132 cursor = No_Cursor;
35133
35134 if (!row->reversed_p)
35135 {
35136 hlinfo->mouse_face_beg_col = hpos;
35137 hlinfo->mouse_face_beg_x = original_x_pixel
35138 - (total_pixel_width + dx);
35139 hlinfo->mouse_face_end_col = hpos + gseq_length;
35140 hlinfo->mouse_face_end_x = 0;
35141 }
35142 else
35143 {
35144
35145
35146 hlinfo->mouse_face_end_col = hpos;
35147 hlinfo->mouse_face_end_x = original_x_pixel
35148 - (total_pixel_width + dx);
35149 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35150 hlinfo->mouse_face_beg_x = 0;
35151 }
35152
35153 hlinfo->mouse_face_beg_row = vpos;
35154 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35155 hlinfo->mouse_face_past_end = false;
35156 hlinfo->mouse_face_window = window;
35157
35158 hlinfo->mouse_face_face_id =
35159 face_at_string_position (w, string, charpos, 0, &ignore,
35160 glyph->face_id, true, 0);
35161
35162 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35163 mouse_face_shown = true;
35164
35165 if (NILP (pointer))
35166 pointer = Qhand;
35167 }
35168 }
35169
35170
35171
35172 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35173 || area == ON_TAB_LINE) && !mouse_face_shown)
35174 clear_mouse_face (hlinfo);
35175
35176 define_frame_cursor1 (f, cursor, pointer);
35177 }
35178
35179
35180
35181
35182
35183
35184
35185
35186
35187
35188 void
35189 note_mouse_highlight (struct frame *f, int x, int y)
35190 {
35191 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35192 enum window_part part = ON_NOTHING;
35193 Lisp_Object window;
35194 struct window *w;
35195 Emacs_Cursor cursor = No_Cursor;
35196 Lisp_Object pointer = Qnil;
35197 struct buffer *b;
35198
35199
35200 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS)
35201 if (popup_activated ())
35202 return;
35203 #endif
35204
35205 #if defined (HAVE_HAIKU)
35206 if (popup_activated_p)
35207 return;
35208 #endif
35209
35210 if (!f->glyphs_initialized_p
35211 || f->pointer_invisible)
35212 return;
35213
35214 hlinfo->mouse_face_mouse_x = x;
35215 hlinfo->mouse_face_mouse_y = y;
35216 hlinfo->mouse_face_mouse_frame = f;
35217
35218 if (hlinfo->mouse_face_defer)
35219 return;
35220
35221
35222 window = window_from_coordinates (f, x, y, &part, true, true);
35223
35224
35225 if (! EQ (window, hlinfo->mouse_face_window)
35226
35227 || (!NILP (hlinfo->mouse_face_window)
35228 && !NILP (window)
35229 && part != ON_TEXT
35230 && part != ON_MODE_LINE
35231 && part != ON_HEADER_LINE
35232 && part != ON_TAB_LINE))
35233 clear_mouse_face (hlinfo);
35234
35235
35236 help_echo_string = Qnil;
35237
35238
35239 if (!FRAME_WINDOW_P (f)
35240 && (y >= FRAME_MENU_BAR_LINES (f)
35241 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35242 {
35243 int prop_idx;
35244 bool ignore;
35245 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35246
35247 if (!NILP (caption))
35248 {
35249 help_echo_object = help_echo_window = Qnil;
35250 help_echo_pos = -1;
35251 help_echo_string = AREF (f->tab_bar_items,
35252 prop_idx * TAB_BAR_ITEM_NSLOTS
35253 + TAB_BAR_ITEM_HELP);
35254 if (NILP (help_echo_string))
35255 help_echo_string = caption;
35256 }
35257 }
35258
35259 #ifdef HAVE_WINDOW_SYSTEM
35260
35261
35262 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35263 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35264 {
35265 enum internal_border_part part = frame_internal_border_part (f, x, y);
35266
35267 switch (part)
35268 {
35269 case INTERNAL_BORDER_NONE:
35270 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35271
35272 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35273 break;
35274 case INTERNAL_BORDER_LEFT_EDGE:
35275 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35276 break;
35277 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35278 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35279 break;
35280 case INTERNAL_BORDER_TOP_EDGE:
35281 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35282 break;
35283 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35284 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35285 break;
35286 case INTERNAL_BORDER_RIGHT_EDGE:
35287 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35288 break;
35289 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35290 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35291 break;
35292 case INTERNAL_BORDER_BOTTOM_EDGE:
35293 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35294 break;
35295 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35296 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35297 break;
35298 default:
35299
35300 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35301 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35302 }
35303
35304 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35305 {
35306
35307 help_echo_string = build_string ("drag-mouse-1: resize frame");
35308 goto set_cursor;
35309 }
35310 }
35311 #endif
35312
35313
35314 if (!WINDOWP (window))
35315 return;
35316
35317
35318 w = XWINDOW (window);
35319 frame_to_window_pixel_xy (w, &x, &y);
35320
35321 #if defined (HAVE_WINDOW_SYSTEM)
35322
35323
35324 if (EQ (window, f->tab_bar_window))
35325 {
35326 note_tab_bar_highlight (f, x, y);
35327 if (tab_bar__dragging_in_progress)
35328 {
35329 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35330 goto set_cursor;
35331 }
35332 else
35333 return;
35334 }
35335 else
35336 {
35337
35338
35339
35340
35341 f->last_tab_bar_item = -1;
35342 }
35343 #endif
35344
35345 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35346
35347
35348 if (EQ (window, f->tool_bar_window))
35349 {
35350 note_tool_bar_highlight (f, x, y);
35351 return;
35352 }
35353 #endif
35354
35355
35356 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35357 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35358 {
35359 note_mode_line_or_margin_highlight (window, x, y, part);
35360
35361 #ifdef HAVE_WINDOW_SYSTEM
35362 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35363 {
35364 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35365
35366 goto set_cursor;
35367 }
35368 else
35369 #endif
35370 return;
35371 }
35372
35373 #ifdef HAVE_WINDOW_SYSTEM
35374 if (part == ON_VERTICAL_BORDER)
35375 {
35376 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35377 help_echo_string = build_string ("drag-mouse-1: resize");
35378 goto set_cursor;
35379 }
35380 else if (part == ON_RIGHT_DIVIDER)
35381 {
35382 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35383 help_echo_string = build_string ("drag-mouse-1: resize");
35384 goto set_cursor;
35385 }
35386 else if (part == ON_BOTTOM_DIVIDER)
35387 if (! WINDOW_BOTTOMMOST_P (w)
35388 || minibuf_level
35389 || NILP (Vresize_mini_windows))
35390 {
35391 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35392 help_echo_string = build_string ("drag-mouse-1: resize");
35393 goto set_cursor;
35394 }
35395 else
35396 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35397 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35398 || part == ON_VERTICAL_SCROLL_BAR
35399 || part == ON_HORIZONTAL_SCROLL_BAR)
35400 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35401 else
35402 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35403 #endif
35404
35405
35406
35407 b = XBUFFER (w->contents);
35408 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35409 {
35410 int hpos, vpos, dx, dy, area = LAST_AREA;
35411 ptrdiff_t pos;
35412 struct glyph *glyph;
35413 Lisp_Object object;
35414 Lisp_Object mouse_face = Qnil, position;
35415 Lisp_Object *overlay_vec = NULL;
35416 ptrdiff_t i, noverlays;
35417 struct buffer *obuf;
35418 ptrdiff_t obegv, ozv;
35419 bool same_region;
35420
35421
35422 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35423
35424 #ifdef HAVE_WINDOW_SYSTEM
35425
35426 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35427 {
35428 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35429 if (img != NULL && IMAGEP (img->spec))
35430 {
35431 Lisp_Object image_map, hotspot;
35432 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35433 !NILP (image_map))
35434 && (hotspot = find_hot_spot (image_map,
35435 glyph->slice.img.x + dx,
35436 glyph->slice.img.y + dy),
35437 CONSP (hotspot))
35438 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35439 {
35440 Lisp_Object plist;
35441
35442
35443
35444
35445
35446 hotspot = XCDR (hotspot);
35447 if (CONSP (hotspot)
35448 && (plist = XCAR (hotspot), CONSP (plist)))
35449 {
35450 pointer = plist_get (plist, Qpointer);
35451 if (NILP (pointer))
35452 pointer = Qhand;
35453 help_echo_string = plist_get (plist, Qhelp_echo);
35454 if (!NILP (help_echo_string))
35455 {
35456 help_echo_window = window;
35457 help_echo_object = glyph->object;
35458 help_echo_pos = glyph->charpos;
35459 }
35460 }
35461 }
35462 if (NILP (pointer))
35463 pointer = plist_get (XCDR (img->spec), QCpointer);
35464 }
35465 }
35466 #endif
35467
35468
35469 if (glyph == NULL
35470 || area != TEXT_AREA
35471 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35472
35473
35474
35475
35476
35477 || NILP (glyph->object)
35478
35479
35480
35481
35482 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35483 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35484 && glyph->type == STRETCH_GLYPH
35485 && glyph->avoid_cursor_p))
35486 {
35487 if (clear_mouse_face (hlinfo))
35488 cursor = No_Cursor;
35489 if (FRAME_WINDOW_P (f) && NILP (pointer))
35490 {
35491 #ifdef HAVE_WINDOW_SYSTEM
35492 if (area != TEXT_AREA)
35493 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35494 else
35495 pointer = Vvoid_text_area_pointer;
35496 #endif
35497 }
35498 goto set_cursor;
35499 }
35500
35501 pos = glyph->charpos;
35502 object = glyph->object;
35503 if (!STRINGP (object) && !BUFFERP (object))
35504 goto set_cursor;
35505
35506
35507 if (BUFFERP (object) && pos > BUF_Z (b))
35508 goto set_cursor;
35509
35510
35511
35512 obuf = current_buffer;
35513 current_buffer = b;
35514 obegv = BEGV;
35515 ozv = ZV;
35516 BEGV = BEG;
35517 ZV = Z;
35518
35519
35520 position = make_fixnum (pos);
35521
35522 USE_SAFE_ALLOCA;
35523
35524 if (BUFFERP (object))
35525 {
35526
35527 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35528
35529 noverlays = sort_overlays (overlay_vec, noverlays, w);
35530 }
35531 else
35532 noverlays = 0;
35533
35534 if (NILP (Vmouse_highlight))
35535 {
35536 clear_mouse_face (hlinfo);
35537 goto check_help_echo;
35538 }
35539
35540 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35541
35542 if (same_region)
35543 cursor = No_Cursor;
35544
35545
35546 if (! same_region
35547
35548
35549
35550
35551
35552 || (!hlinfo->mouse_face_hidden
35553 && OVERLAYP (hlinfo->mouse_face_overlay)
35554
35555 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35556 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35557 {
35558
35559 Lisp_Object overlay = Qnil;
35560 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35561 {
35562 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35563 if (!NILP (mouse_face))
35564 overlay = overlay_vec[i];
35565 }
35566
35567
35568
35569 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35570 goto check_help_echo;
35571
35572
35573 if (clear_mouse_face (hlinfo))
35574 cursor = No_Cursor;
35575
35576
35577 hlinfo->mouse_face_overlay = overlay;
35578
35579
35580 if (NILP (overlay))
35581 mouse_face = Fget_text_property (position, Qmouse_face, object);
35582
35583
35584
35585 if (!NILP (mouse_face) && STRINGP (object))
35586 {
35587
35588
35589 Lisp_Object s, e;
35590 ptrdiff_t ignore;
35591
35592 s = Fprevious_single_property_change
35593 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35594 e = Fnext_single_property_change
35595 (position, Qmouse_face, object, Qnil);
35596 if (NILP (s))
35597 s = make_fixnum (0);
35598 if (NILP (e))
35599 e = make_fixnum (SCHARS (object));
35600 mouse_face_from_string_pos (w, hlinfo, object,
35601 XFIXNUM (s), XFIXNUM (e));
35602 hlinfo->mouse_face_past_end = false;
35603 hlinfo->mouse_face_window = window;
35604 hlinfo->mouse_face_face_id
35605 = face_at_string_position (w, object, pos, 0, &ignore,
35606 glyph->face_id, true, 0);
35607 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35608 cursor = No_Cursor;
35609 }
35610 else
35611 {
35612
35613
35614 Lisp_Object buffer UNINIT;
35615 Lisp_Object disp_string UNINIT;
35616
35617 if (STRINGP (object))
35618 {
35619
35620
35621 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35622 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35623 pos = string_buffer_position (object, start);
35624 if (pos > 0)
35625 {
35626 mouse_face = get_char_property_and_overlay
35627 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35628 buffer = w->contents;
35629 disp_string = object;
35630 }
35631 }
35632 else
35633 {
35634 buffer = object;
35635 disp_string = Qnil;
35636 }
35637
35638 if (!NILP (mouse_face))
35639 {
35640 Lisp_Object before, after;
35641 Lisp_Object before_string, after_string;
35642
35643
35644
35645
35646
35647
35648
35649
35650
35651
35652 Lisp_Object lim1
35653 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35654 ? Fmarker_position (w->start)
35655 : Qnil;
35656 Lisp_Object lim2
35657 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35658 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35659 - w->window_end_pos)
35660 : Qnil;
35661
35662 if (NILP (overlay))
35663 {
35664
35665 before = Fprevious_single_property_change
35666 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35667 after = Fnext_single_property_change
35668 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35669 before_string = after_string = Qnil;
35670 }
35671 else
35672 {
35673
35674 before = Foverlay_start (overlay);
35675 after = Foverlay_end (overlay);
35676 before_string = Foverlay_get (overlay, Qbefore_string);
35677 after_string = Foverlay_get (overlay, Qafter_string);
35678
35679 if (!STRINGP (before_string)) before_string = Qnil;
35680 if (!STRINGP (after_string)) after_string = Qnil;
35681 }
35682
35683 mouse_face_from_buffer_pos (window, hlinfo, pos,
35684 NILP (before)
35685 ? 1
35686 : XFIXNAT (before),
35687 NILP (after)
35688 ? BUF_Z (XBUFFER (buffer))
35689 : XFIXNAT (after),
35690 before_string, after_string,
35691 disp_string);
35692 cursor = No_Cursor;
35693 }
35694 }
35695 }
35696
35697 check_help_echo:
35698
35699
35700 if (NILP (help_echo_string)) {
35701 Lisp_Object help, overlay;
35702
35703
35704 help = overlay = Qnil;
35705 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35706 {
35707 overlay = overlay_vec[i];
35708 help = Foverlay_get (overlay, Qhelp_echo);
35709 }
35710
35711 if (!NILP (help))
35712 {
35713 help_echo_string = help;
35714 help_echo_window = window;
35715 help_echo_object = overlay;
35716 help_echo_pos = pos;
35717 }
35718 else
35719 {
35720 Lisp_Object obj = glyph->object;
35721 ptrdiff_t charpos = glyph->charpos;
35722
35723
35724 if (STRINGP (obj)
35725 && charpos >= 0
35726 && charpos < SCHARS (obj))
35727 {
35728 help = Fget_text_property (make_fixnum (charpos),
35729 Qhelp_echo, obj);
35730 if (NILP (help))
35731 {
35732
35733
35734 struct glyph_row *r
35735 = MATRIX_ROW (w->current_matrix, vpos);
35736 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35737 ptrdiff_t p = string_buffer_position (obj, start);
35738 if (p > 0)
35739 {
35740 help = Fget_char_property (make_fixnum (p),
35741 Qhelp_echo, w->contents);
35742 if (!NILP (help))
35743 {
35744 charpos = p;
35745 obj = w->contents;
35746 }
35747 }
35748 }
35749 }
35750 else if (BUFFERP (obj)
35751 && charpos >= BEGV
35752 && charpos < ZV)
35753 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35754 obj);
35755
35756 if (!NILP (help))
35757 {
35758 help_echo_string = help;
35759 help_echo_window = window;
35760 help_echo_object = obj;
35761 help_echo_pos = charpos;
35762 }
35763 }
35764 }
35765
35766 #ifdef HAVE_WINDOW_SYSTEM
35767
35768 if (FRAME_WINDOW_P (f) && NILP (pointer))
35769 {
35770
35771 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35772 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35773
35774 if (NILP (pointer))
35775 {
35776 Lisp_Object obj = glyph->object;
35777 ptrdiff_t charpos = glyph->charpos;
35778
35779
35780 if (STRINGP (obj)
35781 && charpos >= 0
35782 && charpos < SCHARS (obj))
35783 {
35784 pointer = Fget_text_property (make_fixnum (charpos),
35785 Qpointer, obj);
35786 if (NILP (pointer))
35787 {
35788
35789
35790 struct glyph_row *r
35791 = MATRIX_ROW (w->current_matrix, vpos);
35792 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35793 ptrdiff_t p = string_buffer_position (obj, start);
35794 if (p > 0)
35795 pointer = Fget_char_property (make_fixnum (p),
35796 Qpointer, w->contents);
35797 }
35798 }
35799 else if (BUFFERP (obj)
35800 && charpos >= BEGV
35801 && charpos < ZV)
35802 pointer = Fget_text_property (make_fixnum (charpos),
35803 Qpointer, obj);
35804 }
35805 }
35806 #endif
35807
35808 BEGV = obegv;
35809 ZV = ozv;
35810 current_buffer = obuf;
35811 SAFE_FREE ();
35812 }
35813
35814 set_cursor:
35815 define_frame_cursor1 (f, cursor, pointer);
35816 }
35817
35818
35819
35820
35821
35822
35823
35824 void
35825 gui_clear_window_mouse_face (struct window *w)
35826 {
35827 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35828 Lisp_Object window;
35829
35830 block_input ();
35831 XSETWINDOW (window, w);
35832 if (EQ (window, hlinfo->mouse_face_window))
35833 clear_mouse_face (hlinfo);
35834 unblock_input ();
35835 }
35836
35837
35838
35839
35840
35841
35842 void
35843 cancel_mouse_face (struct frame *f)
35844 {
35845 Lisp_Object window;
35846 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35847
35848 window = hlinfo->mouse_face_window;
35849 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35850 reset_mouse_highlight (hlinfo);
35851 }
35852
35853
35854
35855
35856
35857
35858
35859 #ifdef HAVE_WINDOW_SYSTEM
35860
35861
35862
35863
35864 static void
35865 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
35866 enum glyph_row_area area)
35867 {
35868 struct glyph *first = row->glyphs[area];
35869 struct glyph *end = row->glyphs[area] + row->used[area];
35870 struct glyph *last;
35871 int first_x, start_x, x;
35872
35873 if (area == TEXT_AREA && row->fill_line_p)
35874
35875 draw_glyphs (w, row->x, row, area,
35876 0, row->used[area],
35877 DRAW_NORMAL_TEXT, 0);
35878 else
35879 {
35880
35881
35882
35883 start_x = window_box_left_offset (w, area);
35884 x = start_x;
35885 if (area == TEXT_AREA)
35886 x += row->x;
35887
35888
35889 while (first < end
35890 && x + first->pixel_width < r->x)
35891 {
35892 x += first->pixel_width;
35893 ++first;
35894 }
35895
35896
35897 last = first;
35898 first_x = x;
35899
35900
35901
35902 int r_end = r->x + r->width;
35903 while (last < end && x < r_end)
35904 {
35905 x += last->pixel_width;
35906 ++last;
35907 }
35908
35909
35910 if (last > first)
35911 draw_glyphs (w, first_x - start_x, row, area,
35912 first - row->glyphs[area], last - row->glyphs[area],
35913 DRAW_NORMAL_TEXT, 0);
35914 }
35915 }
35916
35917
35918
35919
35920
35921
35922 static bool
35923 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
35924 {
35925 eassert (row->enabled_p);
35926
35927 if (row->mode_line_p || w->pseudo_window_p)
35928 draw_glyphs (w, 0, row, TEXT_AREA,
35929 0, row->used[TEXT_AREA],
35930 DRAW_NORMAL_TEXT, 0);
35931 else
35932 {
35933 if (row->used[LEFT_MARGIN_AREA])
35934 expose_area (w, row, r, LEFT_MARGIN_AREA);
35935 if (row->used[TEXT_AREA])
35936 expose_area (w, row, r, TEXT_AREA);
35937 if (row->used[RIGHT_MARGIN_AREA])
35938 expose_area (w, row, r, RIGHT_MARGIN_AREA);
35939 draw_row_fringe_bitmaps (w, row);
35940 }
35941
35942 return row->mouse_face_p;
35943 }
35944
35945
35946
35947
35948
35949
35950
35951
35952
35953
35954 static void
35955 expose_overlaps (struct window *w,
35956 struct glyph_row *first_overlapping_row,
35957 struct glyph_row *last_overlapping_row,
35958 const Emacs_Rectangle *r)
35959 {
35960 struct glyph_row *row;
35961
35962 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
35963 if (row->overlapping_p)
35964 {
35965 eassert (row->enabled_p && !row->mode_line_p);
35966
35967 row->clip = r;
35968 if (row->used[LEFT_MARGIN_AREA])
35969 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
35970
35971 if (row->used[TEXT_AREA])
35972 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
35973
35974 if (row->used[RIGHT_MARGIN_AREA])
35975 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
35976 row->clip = NULL;
35977 }
35978 }
35979
35980
35981
35982
35983 static bool
35984 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
35985 {
35986 Emacs_Rectangle cr, result;
35987 struct glyph *cursor_glyph;
35988 struct glyph_row *row;
35989
35990 if (w->phys_cursor.vpos >= 0
35991 && w->phys_cursor.vpos < w->current_matrix->nrows
35992 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
35993 row->enabled_p)
35994 && row->cursor_in_fringe_p)
35995 {
35996
35997 cr.x = window_box_right_offset (w,
35998 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
35999 ? RIGHT_MARGIN_AREA
36000 : TEXT_AREA));
36001 cr.y = row->y;
36002 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36003 cr.height = row->height;
36004 return gui_intersect_rectangles (&cr, r, &result);
36005 }
36006
36007 cursor_glyph = get_phys_cursor_glyph (w);
36008 if (cursor_glyph)
36009 {
36010
36011
36012 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36013 cr.y = w->phys_cursor.y;
36014 cr.width = cursor_glyph->pixel_width;
36015 cr.height = w->phys_cursor_height;
36016
36017
36018 return gui_intersect_rectangles (&cr, r, &result);
36019 }
36020
36021 return false;
36022 }
36023
36024
36025
36026
36027
36028
36029 void
36030 gui_draw_vertical_border (struct window *w)
36031 {
36032 struct frame *f = XFRAME (WINDOW_FRAME (w));
36033
36034
36035
36036
36037
36038
36039
36040
36041
36042 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36043 return;
36044
36045
36046
36047
36048 if (!WINDOW_RIGHTMOST_P (w)
36049 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36050 {
36051 int x0, x1, y0, y1;
36052
36053 window_box_edges (w, &x0, &y0, &x1, &y1);
36054 y1 -= 1;
36055
36056 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36057 x1 -= 1;
36058
36059 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36060 }
36061
36062 if (!WINDOW_LEFTMOST_P (w)
36063 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36064 {
36065 int x0, x1, y0, y1;
36066
36067 window_box_edges (w, &x0, &y0, &x1, &y1);
36068 y1 -= 1;
36069
36070 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36071 x0 -= 1;
36072
36073 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36074 }
36075 }
36076
36077
36078
36079
36080 void
36081 gui_draw_right_divider (struct window *w)
36082 {
36083 struct frame *f = WINDOW_XFRAME (w);
36084
36085 if (w->mini || w->pseudo_window_p)
36086 return;
36087 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36088 {
36089 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36090 int x1 = WINDOW_RIGHT_EDGE_X (w);
36091 int y0 = WINDOW_TOP_EDGE_Y (w);
36092 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36093
36094
36095
36096 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36097 && !NILP (w->parent)
36098 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36099 && !NILP (w->next))
36100 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36101
36102 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36103 }
36104 }
36105
36106 static void
36107 gui_draw_bottom_divider (struct window *w)
36108 {
36109 struct frame *f = XFRAME (WINDOW_FRAME (w));
36110
36111 if (w->mini || w->pseudo_window_p)
36112 return;
36113 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36114 {
36115 int x0 = WINDOW_LEFT_EDGE_X (w);
36116 int x1 = WINDOW_RIGHT_EDGE_X (w);
36117 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36118 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36119 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36120
36121
36122
36123 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36124 && p
36125 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36126 && !NILP (w->next))
36127 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36128 && NILP (w->next)
36129 && !NILP (p->parent)
36130 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36131 && !NILP (XWINDOW (p->parent)->next))))
36132 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36133
36134 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36135 }
36136 }
36137
36138
36139
36140
36141
36142
36143 static bool
36144 expose_window (struct window *w, const Emacs_Rectangle *fr)
36145 {
36146 struct frame *f = XFRAME (w->frame);
36147 Emacs_Rectangle wr, r;
36148 bool mouse_face_overwritten_p = false;
36149
36150
36151
36152
36153
36154 if (w->current_matrix == NULL)
36155 return false;
36156
36157
36158
36159
36160 if (w->must_be_updated_p)
36161 {
36162 SET_FRAME_GARBAGED (f);
36163 return false;
36164 }
36165
36166
36167 wr.x = WINDOW_LEFT_EDGE_X (w);
36168 wr.y = WINDOW_TOP_EDGE_Y (w);
36169 wr.width = WINDOW_PIXEL_WIDTH (w);
36170 wr.height = WINDOW_PIXEL_HEIGHT (w);
36171
36172 if (gui_intersect_rectangles (fr, &wr, &r))
36173 {
36174 int yb = window_text_bottom_y (w);
36175 struct glyph_row *row;
36176 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36177
36178 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36179 r.x, r.y, r.width, r.height);
36180
36181
36182 r.x -= WINDOW_LEFT_EDGE_X (w);
36183 r.y -= WINDOW_TOP_EDGE_Y (w);
36184
36185
36186 bool cursor_cleared_p = (!w->pseudo_window_p
36187 && phys_cursor_in_rect_p (w, &r));
36188 if (cursor_cleared_p)
36189 gui_clear_cursor (w);
36190
36191
36192
36193
36194
36195
36196 bool phys_cursor_on_p = w->phys_cursor_on_p;
36197
36198
36199
36200
36201 int r_bottom = r.y + r.height;
36202
36203
36204
36205
36206
36207 bool buffer_changed = false;
36208 struct buffer *oldbuf = current_buffer;
36209 if (!w->pseudo_window_p)
36210 {
36211 set_buffer_internal_1 (XBUFFER (w->contents));
36212 buffer_changed = true;
36213 }
36214
36215
36216 first_overlapping_row = last_overlapping_row = NULL;
36217 for (row = w->current_matrix->rows;
36218 row->enabled_p;
36219 ++row)
36220 {
36221 int y0 = row->y;
36222 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36223
36224 if ((y0 >= r.y && y0 < r_bottom)
36225 || (y1 > r.y && y1 < r_bottom)
36226 || (r.y >= y0 && r.y < y1)
36227 || (r_bottom > y0 && r_bottom < y1))
36228 {
36229
36230
36231 if (row->overlapping_p && !row->mode_line_p)
36232 {
36233 if (first_overlapping_row == NULL)
36234 first_overlapping_row = row;
36235 last_overlapping_row = row;
36236 }
36237
36238 row->clip = fr;
36239 if (expose_line (w, row, &r))
36240 mouse_face_overwritten_p = true;
36241 row->clip = NULL;
36242 }
36243 else if (row->overlapping_p)
36244 {
36245
36246 if (y0 < r.y
36247 ? y0 + row->phys_height > r.y
36248 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36249 {
36250 if (first_overlapping_row == NULL)
36251 first_overlapping_row = row;
36252 last_overlapping_row = row;
36253 }
36254 }
36255
36256 if (y1 >= yb)
36257 break;
36258 }
36259
36260 if (buffer_changed)
36261 set_buffer_internal_1 (oldbuf);
36262
36263
36264 if (window_wants_mode_line (w)
36265 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36266 row->enabled_p)
36267 && row->y < r_bottom)
36268 {
36269 if (expose_line (w, row, &r))
36270 mouse_face_overwritten_p = true;
36271 }
36272
36273 if (!w->pseudo_window_p)
36274 {
36275
36276 if (first_overlapping_row)
36277 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36278 fr);
36279
36280
36281 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36282 gui_draw_right_divider (w);
36283 else
36284 gui_draw_vertical_border (w);
36285
36286 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36287 gui_draw_bottom_divider (w);
36288
36289
36290 if (cursor_cleared_p
36291 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36292 update_window_cursor (w, true);
36293 }
36294 }
36295
36296 return mouse_face_overwritten_p;
36297 }
36298
36299
36300
36301
36302
36303
36304
36305 static bool
36306 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36307 {
36308 struct frame *f = XFRAME (w->frame);
36309 bool mouse_face_overwritten_p = false;
36310
36311 while (w && !FRAME_GARBAGED_P (f))
36312 {
36313 mouse_face_overwritten_p
36314 |= (WINDOWP (w->contents)
36315 ? expose_window_tree (XWINDOW (w->contents), r)
36316 : expose_window (w, r));
36317
36318 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36319 }
36320
36321 return mouse_face_overwritten_p;
36322 }
36323
36324
36325
36326
36327
36328
36329
36330
36331 void
36332 expose_frame (struct frame *f, int x, int y, int w, int h)
36333 {
36334 Emacs_Rectangle r;
36335 bool mouse_face_overwritten_p = false;
36336
36337 if (FRAME_GARBAGED_P (f))
36338 {
36339 redisplay_trace ("expose_frame garbaged\n");
36340 return;
36341 }
36342
36343
36344
36345
36346 if (FRAME_FACE_CACHE (f) == NULL
36347 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36348 {
36349 redisplay_trace ("expose_frame no faces\n");
36350 return;
36351 }
36352
36353 if (w == 0 || h == 0)
36354 {
36355 r.x = r.y = 0;
36356 r.width = FRAME_TEXT_WIDTH (f);
36357 r.height = FRAME_TEXT_HEIGHT (f);
36358 }
36359 else
36360 {
36361 r.x = x;
36362 r.y = y;
36363 r.width = w;
36364 r.height = h;
36365 }
36366
36367 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36368 r.x, r.y, r.width, r.height);
36369 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36370
36371 if (WINDOWP (f->tab_bar_window))
36372 mouse_face_overwritten_p
36373 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36374
36375 #ifndef HAVE_EXT_TOOL_BAR
36376 if (WINDOWP (f->tool_bar_window))
36377 mouse_face_overwritten_p
36378 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36379 #endif
36380
36381 #ifdef HAVE_X_WINDOWS
36382 #ifndef MSDOS
36383 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
36384 if (WINDOWP (f->menu_bar_window))
36385 mouse_face_overwritten_p
36386 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36387 #endif
36388 #endif
36389 #endif
36390
36391
36392
36393
36394
36395
36396
36397
36398
36399
36400
36401
36402
36403
36404 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36405 {
36406 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36407 if (f == hlinfo->mouse_face_mouse_frame)
36408 {
36409 int mouse_x = hlinfo->mouse_face_mouse_x;
36410 int mouse_y = hlinfo->mouse_face_mouse_y;
36411 clear_mouse_face (hlinfo);
36412 note_mouse_highlight (f, mouse_x, mouse_y);
36413 }
36414 }
36415 }
36416
36417
36418
36419
36420
36421
36422
36423 bool
36424 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36425 Emacs_Rectangle *result)
36426 {
36427 const Emacs_Rectangle *left, *right;
36428 const Emacs_Rectangle *upper, *lower;
36429 bool intersection_p = false;
36430
36431
36432 if (r1->x < r2->x)
36433 left = r1, right = r2;
36434 else
36435 left = r2, right = r1;
36436
36437
36438
36439 if (right->x <= left->x + left->width)
36440 {
36441 result->x = right->x;
36442
36443
36444
36445 result->width = (min (left->x + left->width, right->x + right->width)
36446 - result->x);
36447
36448
36449 if (r1->y < r2->y)
36450 upper = r1, lower = r2;
36451 else
36452 upper = r2, lower = r1;
36453
36454
36455
36456 if (lower->y <= upper->y + upper->height)
36457 {
36458 result->y = lower->y;
36459
36460
36461
36462 result->height = (min (lower->y + lower->height,
36463 upper->y + upper->height)
36464 - result->y);
36465 intersection_p = true;
36466 }
36467 }
36468
36469 return intersection_p;
36470 }
36471
36472 #endif
36473
36474
36475
36476
36477
36478
36479 void
36480 syms_of_xdisp (void)
36481 {
36482 Vwith_echo_area_save_vector = Qnil;
36483 staticpro (&Vwith_echo_area_save_vector);
36484
36485 Vmessage_stack = Qnil;
36486 staticpro (&Vmessage_stack);
36487
36488
36489 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36490
36491 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36492
36493 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36494 scroll_minibuffer_conservatively,
36495 doc:
36496
36497 );
36498 scroll_minibuffer_conservatively = true;
36499
36500 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36501 doc:
36502
36503
36504
36505
36506
36507 );
36508 inhibit_message = false;
36509
36510 message_dolog_marker1 = Fmake_marker ();
36511 staticpro (&message_dolog_marker1);
36512 message_dolog_marker2 = Fmake_marker ();
36513 staticpro (&message_dolog_marker2);
36514 message_dolog_marker3 = Fmake_marker ();
36515 staticpro (&message_dolog_marker3);
36516
36517 defsubr (&Sset_buffer_redisplay);
36518 #ifdef GLYPH_DEBUG
36519 defsubr (&Sdump_frame_glyph_matrix);
36520 defsubr (&Sdump_glyph_matrix);
36521 defsubr (&Sdump_glyph_row);
36522 defsubr (&Sdump_tab_bar_row);
36523 defsubr (&Sdump_tool_bar_row);
36524 defsubr (&Strace_redisplay);
36525 defsubr (&Strace_to_stderr);
36526 #endif
36527 #ifdef HAVE_WINDOW_SYSTEM
36528 defsubr (&Stab_bar_height);
36529 defsubr (&Stool_bar_height);
36530 defsubr (&Slookup_image_map);
36531 #endif
36532 defsubr (&Sline_pixel_height);
36533 defsubr (&Sformat_mode_line);
36534 defsubr (&Sinvisible_p);
36535 defsubr (&Scurrent_bidi_paragraph_direction);
36536 defsubr (&Swindow_text_pixel_size);
36537 defsubr (&Sbuffer_text_pixel_size);
36538 defsubr (&Smove_point_visually);
36539 defsubr (&Sbidi_find_overridden_directionality);
36540 defsubr (&Sdisplay__line_is_continued_p);
36541 defsubr (&Sget_display_property);
36542 defsubr (&Slong_line_optimizations_p);
36543
36544 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36545 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36546 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36547 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36548 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36549 DEFSYM (Qeval, "eval");
36550 DEFSYM (QCdata, ":data");
36551
36552
36553 DEFSYM (Qdisplay, "display");
36554 DEFSYM (Qspace_width, "space-width");
36555 DEFSYM (Qraise, "raise");
36556 DEFSYM (Qslice, "slice");
36557 DEFSYM (Qspace, "space");
36558 DEFSYM (Qmargin, "margin");
36559 DEFSYM (Qpointer, "pointer");
36560 DEFSYM (Qleft_margin, "left-margin");
36561 DEFSYM (Qright_margin, "right-margin");
36562 DEFSYM (Qcenter, "center");
36563 DEFSYM (Qline_height, "line-height");
36564 DEFSYM (QCalign_to, ":align-to");
36565 DEFSYM (QCrelative_width, ":relative-width");
36566 DEFSYM (QCrelative_height, ":relative-height");
36567 DEFSYM (QCeval, ":eval");
36568 DEFSYM (QCpropertize, ":propertize");
36569 DEFSYM (QCfile, ":file");
36570 DEFSYM (Qfontified, "fontified");
36571 DEFSYM (Qfontification_functions, "fontification-functions");
36572 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36573 "long-line-optimizations-in-fontification-functions");
36574
36575
36576
36577 DEFSYM (Qdisable_eval, "disable-eval");
36578
36579
36580 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36581
36582
36583 DEFSYM (Qline_number, "line-number");
36584 DEFSYM (Qline_number_current_line, "line-number-current-line");
36585 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36586 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36587
36588 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36589
36590
36591 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36592
36593
36594 DEFSYM (Qescape_glyph, "escape-glyph");
36595
36596
36597
36598 DEFSYM (Qnobreak_space, "nobreak-space");
36599 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36600
36601
36602
36603 DEFSYM (Qimage, "image");
36604
36605
36606 DEFSYM (Qtext, "text");
36607 DEFSYM (Qboth, "both");
36608 DEFSYM (Qboth_horiz, "both-horiz");
36609 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36610
36611
36612 DEFSYM (QCmap, ":map");
36613 DEFSYM (QCpointer, ":pointer");
36614 DEFSYM (Qrect, "rect");
36615 DEFSYM (Qcircle, "circle");
36616 DEFSYM (Qpoly, "poly");
36617
36618 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36619
36620 DEFSYM (Qgrow_only, "grow-only");
36621 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36622 DEFSYM (Qposition, "position");
36623 DEFSYM (Qbuffer_position, "buffer-position");
36624 DEFSYM (Qobject, "object");
36625
36626
36627 DEFSYM (Qbar, "bar");
36628 DEFSYM (Qhbar, "hbar");
36629 DEFSYM (Qbox, "box");
36630 DEFSYM (Qhollow, "hollow");
36631
36632
36633 DEFSYM (Qhand, "hand");
36634 DEFSYM (Qarrow, "arrow");
36635
36636
36637 DEFSYM (Qdragging, "dragging");
36638 DEFSYM (Qdropping, "dropping");
36639 DEFSYM (Qdrag_source, "drag-source");
36640
36641 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36642 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36643 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36644
36645 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36646
36647 list_of_error = list1 (Qerror);
36648 staticpro (&list_of_error);
36649
36650
36651
36652
36653
36654 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36655 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36656
36657
36658
36659 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36660 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36661
36662 echo_buffer[0] = echo_buffer[1] = Qnil;
36663 staticpro (&echo_buffer[0]);
36664 staticpro (&echo_buffer[1]);
36665
36666 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36667 staticpro (&echo_area_buffer[0]);
36668 staticpro (&echo_area_buffer[1]);
36669
36670 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36671 doc:
36672
36673
36674
36675 );
36676 Vmessages_buffer_name = build_string ("*Messages*");
36677
36678 mode_line_proptrans_alist = Qnil;
36679 staticpro (&mode_line_proptrans_alist);
36680 mode_line_string_list = Qnil;
36681 staticpro (&mode_line_string_list);
36682 mode_line_string_face = Qnil;
36683 staticpro (&mode_line_string_face);
36684 mode_line_string_face_prop = Qnil;
36685 staticpro (&mode_line_string_face_prop);
36686 Vmode_line_unwind_vector = Qnil;
36687 staticpro (&Vmode_line_unwind_vector);
36688
36689 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36690
36691 help_echo_string = Qnil;
36692 staticpro (&help_echo_string);
36693 help_echo_object = Qnil;
36694 staticpro (&help_echo_object);
36695 help_echo_window = Qnil;
36696 staticpro (&help_echo_window);
36697 previous_help_echo_string = Qnil;
36698 staticpro (&previous_help_echo_string);
36699 help_echo_pos = -1;
36700
36701 DEFSYM (Qright_to_left, "right-to-left");
36702 DEFSYM (Qleft_to_right, "left-to-right");
36703 defsubr (&Sbidi_resolved_levels);
36704
36705 #ifdef HAVE_WINDOW_SYSTEM
36706 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36707 doc:
36708
36709 );
36710 x_stretch_cursor_p = 0;
36711 #endif
36712
36713 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36714 doc:
36715 );
36716 Vshow_trailing_whitespace = Qnil;
36717
36718 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36719 doc:
36720
36721
36722 );
36723 Vmode_line_compact = Qnil;
36724 DEFSYM (Qlong, "long");
36725
36726 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36727 doc:
36728
36729
36730
36731
36732
36733
36734
36735
36736
36737
36738
36739 );
36740 Vnobreak_char_display = Qt;
36741
36742 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36743 doc:
36744
36745
36746
36747
36748
36749
36750
36751
36752
36753
36754
36755
36756
36757
36758
36759 );
36760 nobreak_char_ascii_display = false;
36761
36762 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36763 doc:
36764
36765
36766 );
36767 Vvoid_text_area_pointer = Qarrow;
36768
36769 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36770 doc:
36771 );
36772 Vinhibit_redisplay = Qnil;
36773
36774 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36775 doc: );
36776 Vglobal_mode_string = Qnil;
36777
36778 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36779 doc:
36780
36781 );
36782 Voverlay_arrow_position = Qnil;
36783
36784 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36785 doc:
36786 );
36787 Voverlay_arrow_string = build_pure_c_string ("=>");
36788
36789 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36790 doc:
36791
36792 );
36793 Voverlay_arrow_variable_list
36794 = list1 (intern_c_string ("overlay-arrow-position"));
36795
36796 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36797 doc:
36798
36799
36800
36801 );
36802
36803 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36804 doc:
36805
36806
36807
36808
36809
36810
36811
36812
36813
36814 );
36815 scroll_conservatively = 0;
36816
36817 DEFVAR_INT ("scroll-margin", scroll_margin,
36818 doc:
36819
36820 );
36821 scroll_margin = 0;
36822
36823 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
36824 doc:
36825
36826
36827
36828 );
36829 Vmaximum_scroll_margin = make_float (0.25);
36830
36831 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
36832 doc:
36833 );
36834 Vdisplay_pixels_per_inch = make_float (72.0);
36835
36836 #ifdef GLYPH_DEBUG
36837 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
36838 #endif
36839
36840 DEFVAR_LISP ("truncate-partial-width-windows",
36841 Vtruncate_partial_width_windows,
36842 doc:
36843
36844
36845
36846
36847
36848
36849
36850
36851
36852
36853
36854
36855
36856
36857
36858 );
36859 Vtruncate_partial_width_windows = make_fixnum (50);
36860
36861 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
36862
36863
36864
36865
36866
36867
36868
36869
36870
36871
36872
36873
36874
36875 );
36876 word_wrap_by_category = false;
36877
36878 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
36879 doc:
36880
36881 );
36882 Vline_number_display_limit = Qnil;
36883
36884 DEFVAR_INT ("line-number-display-limit-width",
36885 line_number_display_limit_width,
36886 doc:
36887
36888 );
36889 line_number_display_limit_width = 200;
36890
36891 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
36892 doc:
36893
36894 );
36895 highlight_nonselected_windows = false;
36896
36897 DEFVAR_BOOL ("multiple-frames", multiple_frames,
36898 doc:
36899
36900
36901 );
36902
36903 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
36904 doc:
36905
36906
36907
36908
36909 );
36910
36911 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
36912 doc:
36913
36914
36915
36916
36917
36918 );
36919
36920
36921 Lisp_Object icon_title_name_format
36922 = pure_list (empty_unibyte_string,
36923 build_pure_c_string ("%b - GNU Emacs at "),
36924 intern_c_string ("system-name"));
36925 Vicon_title_format
36926 = Vframe_title_format
36927 = pure_list (intern_c_string ("multiple-frames"),
36928 build_pure_c_string ("%b"),
36929 icon_title_name_format);
36930
36931 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
36932 doc:
36933
36934 );
36935 Vmessage_log_max = make_fixnum (1000);
36936
36937 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
36938 doc:
36939
36940
36941
36942
36943
36944
36945
36946
36947
36948
36949
36950
36951
36952 );
36953 Vwindow_scroll_functions = Qnil;
36954
36955 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
36956 doc:
36957
36958
36959
36960
36961
36962
36963
36964
36965
36966
36967
36968
36969
36970
36971
36972
36973
36974 );
36975 Vmouse_autoselect_window = Qnil;
36976
36977 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
36978 doc:
36979
36980
36981
36982
36983 );
36984 Vauto_resize_tab_bars = Qt;
36985
36986 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
36987 doc: );
36988 auto_raise_tab_bar_buttons_p = true;
36989
36990 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
36991 doc:
36992
36993
36994
36995
36996 );
36997 Vauto_resize_tool_bars = Qt;
36998
36999 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37000 doc: );
37001 auto_raise_tool_bar_buttons_p = true;
37002
37003 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37004 doc:
37005
37006
37007
37008
37009 );
37010 Vmake_cursor_line_fully_visible = Qt;
37011 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37012
37013 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37014 doc: );
37015 make_window_start_visible = false;
37016 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37017 Fmake_variable_buffer_local (Qmake_window_start_visible);
37018
37019 DEFSYM (Qclose_tab, "close-tab");
37020 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37021 doc:
37022
37023
37024
37025 );
37026 Vtab_bar_border = Qinternal_border_width;
37027
37028 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37029 doc:
37030
37031
37032
37033 );
37034 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37035
37036 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37037 doc: );
37038 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37039
37040 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37041 doc:
37042
37043
37044
37045 );
37046 Vtool_bar_border = Qinternal_border_width;
37047
37048 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37049 doc:
37050
37051
37052
37053 );
37054 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37055
37056 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37057 doc: );
37058 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37059
37060 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37061 doc:
37062
37063
37064
37065
37066
37067
37068
37069
37070 );
37071 Vtool_bar_style = Qnil;
37072
37073 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37074 doc:
37075
37076 );
37077 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37078
37079 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37080 doc:
37081
37082
37083
37084
37085
37086
37087
37088
37089 );
37090 Vfontification_functions = Qnil;
37091 Fmake_variable_buffer_local (Qfontification_functions);
37092
37093 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37094 unibyte_display_via_language_environment,
37095 doc:
37096
37097
37098
37099
37100
37101
37102 );
37103 unibyte_display_via_language_environment = false;
37104
37105 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37106 doc:
37107
37108
37109
37110 );
37111 Vmax_mini_window_height = make_float (0.25);
37112
37113 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37114 doc:
37115
37116
37117
37118
37119
37120
37121
37122
37123 );
37124
37125
37126
37127
37128
37129 Vresize_mini_windows = Qnil;
37130
37131 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37132 doc:
37133
37134
37135
37136
37137
37138
37139
37140 );
37141 Vblink_cursor_alist = Qnil;
37142
37143 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37144 doc:
37145
37146
37147
37148 );
37149 automatic_hscrolling = Qt;
37150 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37151 DEFSYM (Qcurrent_line, "current-line");
37152
37153 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37154 doc:
37155 );
37156 hscroll_margin = 5;
37157
37158 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37159 doc:
37160
37161
37162
37163
37164
37165
37166
37167
37168
37169
37170
37171
37172
37173 );
37174 Vhscroll_step = make_fixnum (0);
37175
37176 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37177 doc:
37178 );
37179 message_truncate_lines = false;
37180
37181 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37182 doc:
37183
37184
37185 );
37186 Vmenu_bar_update_hook = Qnil;
37187
37188 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37189 doc:
37190 );
37191 Vmenu_updating_frame = Qnil;
37192
37193 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37194 doc: );
37195 inhibit_menubar_update = false;
37196
37197 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37198 doc:
37199
37200
37201
37202
37203
37204
37205 );
37206 Vwrap_prefix = Qnil;
37207 DEFSYM (Qwrap_prefix, "wrap-prefix");
37208 Fmake_variable_buffer_local (Qwrap_prefix);
37209
37210 DEFVAR_LISP ("line-prefix", Vline_prefix,
37211 doc:
37212
37213
37214
37215
37216
37217
37218 );
37219 Vline_prefix = Qnil;
37220 DEFSYM (Qline_prefix, "line-prefix");
37221 Fmake_variable_buffer_local (Qline_prefix);
37222
37223 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37224 doc:
37225
37226
37227
37228
37229
37230
37231
37232
37233
37234
37235
37236
37237
37238
37239
37240
37241
37242
37243
37244
37245
37246
37247 );
37248 Vdisplay_line_numbers = Qnil;
37249 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37250 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37251 DEFSYM (Qrelative, "relative");
37252 DEFSYM (Qvisual, "visual");
37253
37254 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37255 doc:
37256
37257
37258
37259 );
37260 Vdisplay_line_numbers_width = Qnil;
37261 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37262 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37263
37264 DEFVAR_LISP ("display-line-numbers-current-absolute",
37265 Vdisplay_line_numbers_current_absolute,
37266 doc:
37267
37268 );
37269 Vdisplay_line_numbers_current_absolute = Qt;
37270
37271 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37272 doc: );
37273 display_line_numbers_widen = false;
37274 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37275 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37276
37277 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37278 doc:
37279
37280
37281 );
37282 display_line_numbers_offset = 0;
37283 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37284 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37285
37286 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37287 doc:
37288
37289
37290 );
37291 display_fill_column_indicator = false;
37292 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37293 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37294
37295 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37296 doc:
37297
37298
37299
37300 );
37301 Vdisplay_fill_column_indicator_column = Qt;
37302 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37303 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37304
37305 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37306 doc:
37307
37308
37309 );
37310 Vdisplay_fill_column_indicator_character = Qnil;
37311 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37312 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37313
37314 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37315 doc:
37316
37317
37318 );
37319 display_line_numbers_major_tick = 0;
37320
37321 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37322 doc:
37323
37324
37325 );
37326 display_line_numbers_minor_tick = 0;
37327
37328 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37329 doc: );
37330 inhibit_eval_during_redisplay = false;
37331
37332 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37333 doc: );
37334 inhibit_free_realized_faces = false;
37335
37336 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37337 doc:
37338
37339 );
37340 inhibit_bidi_mirroring = false;
37341
37342 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37343 doc:
37344
37345
37346
37347 );
37348 bidi_inhibit_bpa = false;
37349
37350 #ifdef GLYPH_DEBUG
37351 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37352 doc: );
37353 inhibit_try_window_id = false;
37354
37355 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37356 doc: );
37357 inhibit_try_window_reusing = false;
37358
37359 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37360 doc: );
37361 inhibit_try_cursor_movement = false;
37362 #endif
37363
37364 DEFVAR_INT ("overline-margin", overline_margin,
37365 doc:
37366
37367 );
37368 overline_margin = 2;
37369
37370 DEFVAR_INT ("underline-minimum-offset",
37371 underline_minimum_offset,
37372 doc:
37373
37374
37375
37376 );
37377 underline_minimum_offset = 1;
37378 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37379
37380 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37381 doc:
37382
37383 );
37384 display_hourglass_p = true;
37385
37386 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37387 doc: );
37388 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37389
37390 #ifdef HAVE_WINDOW_SYSTEM
37391 hourglass_atimer = NULL;
37392 hourglass_shown_p = false;
37393 #endif
37394
37395
37396 DEFSYM (Qglyphless_char, "glyphless-char");
37397
37398
37399 DEFSYM (Qhex_code, "hex-code");
37400 DEFSYM (Qempty_box, "empty-box");
37401 DEFSYM (Qthin_space, "thin-space");
37402 DEFSYM (Qzero_width, "zero-width");
37403
37404 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37405 doc:
37406
37407
37408 );
37409 Vpre_redisplay_function = intern ("ignore");
37410
37411
37412 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37413 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37414
37415 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37416 doc:
37417
37418
37419
37420
37421
37422
37423
37424
37425
37426
37427
37428
37429
37430
37431
37432
37433
37434
37435
37436
37437
37438
37439
37440 );
37441 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37442 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37443 Qempty_box);
37444
37445 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37446 doc: );
37447 Vdebug_on_message = Qnil;
37448
37449 DEFVAR_LISP ("set-message-function", Vset_message_function,
37450 doc:
37451
37452
37453
37454
37455
37456
37457
37458
37459
37460 );
37461 Vset_message_function = Qnil;
37462
37463 DEFSYM (Qdont_clear_message, "dont-clear-message");
37464 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37465 doc:
37466
37467
37468
37469
37470
37471
37472
37473
37474
37475
37476 );
37477 Vclear_message_function = Qnil;
37478
37479 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37480 doc:
37481 );
37482 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37483
37484 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37485 doc:
37486 );
37487 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37488
37489 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37490 doc: );
37491
37492
37493 redisplay__inhibit_bidi = true;
37494
37495 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37496 doc:
37497
37498 );
37499 display_raw_bytes_as_hex = false;
37500
37501 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37502 doc:
37503
37504 );
37505 mouse_fine_grained_tracking = false;
37506
37507 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37508 doc: );
37509 tab_bar__dragging_in_progress = false;
37510
37511 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37512 doc:
37513
37514
37515
37516 );
37517 redisplay_skip_initial_frame = true;
37518
37519 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37520 redisplay_skip_fontification_on_input,
37521 doc:
37522
37523
37524
37525
37526
37527
37528
37529 );
37530 redisplay_skip_fontification_on_input = false;
37531
37532 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37533 redisplay_adhoc_scroll_in_resize_mini_windows,
37534 doc:
37535
37536 );
37537
37538 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37539
37540 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37541 doc:
37542
37543 );
37544 composition_break_at_point = false;
37545
37546 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37547 doc:
37548
37549
37550
37551
37552
37553
37554
37555
37556
37557
37558
37559 );
37560 max_redisplay_ticks = 0;
37561 }
37562
37563
37564
37565
37566 void
37567 init_xdisp (void)
37568 {
37569 CHARPOS (this_line_start_pos) = 0;
37570
37571 echo_area_window = minibuf_window;
37572
37573 if (!noninteractive)
37574 {
37575 struct window *m = XWINDOW (minibuf_window);
37576 Lisp_Object frame = m->frame;
37577 struct frame *f = XFRAME (frame);
37578 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37579 struct window *r = XWINDOW (root);
37580 int i;
37581
37582 r->top_line = FRAME_TOP_MARGIN (f);
37583 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37584 r->total_cols = FRAME_COLS (f);
37585 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37586 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37587 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37588
37589 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37590 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37591 m->total_cols = FRAME_COLS (f);
37592 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37593 m->total_lines = 1;
37594 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37595
37596 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37597 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37598 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37599
37600
37601 for (i = 0; i < 3; ++i)
37602 default_invis_vector[i] = make_fixnum ('.');
37603 }
37604
37605 {
37606
37607
37608 int size = 100;
37609 mode_line_noprop_buf = xmalloc (size);
37610 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37611 mode_line_noprop_ptr = mode_line_noprop_buf;
37612 mode_line_target = MODE_LINE_DISPLAY;
37613 }
37614
37615 help_echo_showing_p = false;
37616 }
37617
37618 #ifdef HAVE_WINDOW_SYSTEM
37619
37620
37621
37622
37623
37624 static void
37625 show_hourglass (struct atimer *timer)
37626 {
37627
37628
37629
37630 hourglass_atimer = NULL;
37631
37632 if (!hourglass_shown_p)
37633 {
37634 Lisp_Object tail, frame;
37635
37636 block_input ();
37637
37638 FOR_EACH_FRAME (tail, frame)
37639 {
37640 struct frame *f = XFRAME (frame);
37641
37642 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37643 && FRAME_RIF (f)->show_hourglass)
37644 FRAME_RIF (f)->show_hourglass (f);
37645 }
37646
37647 hourglass_shown_p = true;
37648 unblock_input ();
37649 }
37650 }
37651
37652
37653
37654 void
37655 start_hourglass (void)
37656 {
37657 struct timespec delay;
37658
37659 cancel_hourglass ();
37660
37661 if (FIXNUMP (Vhourglass_delay)
37662 && XFIXNUM (Vhourglass_delay) > 0)
37663 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37664 TYPE_MAXIMUM (time_t)),
37665 0);
37666 else if (FLOATP (Vhourglass_delay)
37667 && XFLOAT_DATA (Vhourglass_delay) > 0)
37668 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37669 else
37670 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37671
37672 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37673 show_hourglass, NULL);
37674 }
37675
37676
37677
37678
37679 void
37680 cancel_hourglass (void)
37681 {
37682 if (hourglass_atimer)
37683 {
37684 cancel_atimer (hourglass_atimer);
37685 hourglass_atimer = NULL;
37686 }
37687
37688 if (hourglass_shown_p)
37689 {
37690 Lisp_Object tail, frame;
37691
37692 block_input ();
37693
37694 FOR_EACH_FRAME (tail, frame)
37695 {
37696 struct frame *f = XFRAME (frame);
37697
37698 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37699 && FRAME_RIF (f)->hide_hourglass)
37700 FRAME_RIF (f)->hide_hourglass (f);
37701 #ifdef HAVE_NTGUI
37702
37703 else if (!FRAME_W32_P (f))
37704 w32_arrow_cursor ();
37705 #endif
37706 }
37707
37708 hourglass_shown_p = false;
37709 unblock_input ();
37710 }
37711 }
37712
37713
37714
37715
37716
37717
37718
37719
37720 static int
37721 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37722 struct window *w,
37723 struct face *original_face,
37724 struct face *mouse_face)
37725 {
37726 int sum = 0;
37727
37728 bool do_left_box_p = g->left_box_line_p;
37729 bool do_right_box_p = g->right_box_line_p;
37730
37731
37732
37733 if (g->type == IMAGE_GLYPH)
37734 {
37735 if (!row->reversed_p)
37736 {
37737 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37738 g->u.img_id);
37739 do_left_box_p = g->left_box_line_p &&
37740 g->slice.img.x == 0;
37741 do_right_box_p = g->right_box_line_p &&
37742 g->slice.img.x + g->slice.img.width == img->width;
37743 }
37744 else
37745 {
37746 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37747 g->u.img_id);
37748 do_left_box_p = g->left_box_line_p &&
37749 g->slice.img.x + g->slice.img.width == img->width;
37750 do_right_box_p = g->right_box_line_p &&
37751 g->slice.img.x == 0;
37752 }
37753 }
37754
37755
37756 if (do_left_box_p)
37757 sum -= max (0, original_face->box_vertical_line_width);
37758
37759
37760 if (do_right_box_p)
37761 sum -= max (0, original_face->box_vertical_line_width);
37762
37763 if (g->left_box_line_p)
37764 sum += max (0, mouse_face->box_vertical_line_width);
37765 if (g->right_box_line_p)
37766 sum += max (0, mouse_face->box_vertical_line_width);
37767
37768 return sum;
37769 }
37770
37771
37772
37773
37774
37775
37776
37777
37778
37779 static void
37780 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37781 int *offset)
37782 {
37783 int sum = 0;
37784
37785 if (row->mode_line_p)
37786 return;
37787
37788 block_input ();
37789
37790 struct frame *f = WINDOW_XFRAME (w);
37791 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37792 struct glyph *start, *end;
37793 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37794 int hpos = w->phys_cursor.hpos;
37795 end = &row->glyphs[TEXT_AREA][hpos];
37796
37797 if (!row->reversed_p)
37798 {
37799 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37800 hlinfo->mouse_face_beg_row)
37801 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37802 else
37803 start = row->glyphs[TEXT_AREA];
37804 }
37805 else
37806 {
37807 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37808 hlinfo->mouse_face_end_row)
37809 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37810 else
37811 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37812 }
37813
37814
37815
37816
37817 for ( ; row->reversed_p ? start > end : start < end;
37818 row->reversed_p ? --start : ++start)
37819 sum += adjust_glyph_width_for_mouse_face (start, row, w,
37820 FACE_FROM_ID (f, start->face_id),
37821 mouse_face);
37822
37823 if (row->reversed_p)
37824 sum = -sum;
37825
37826 *offset = sum;
37827
37828 unblock_input ();
37829 }
37830 #endif